Finding all files with certain extension in Unix? - macos

I have a file /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
I am trying to find if I have the *.jdk anywhere else on my hard drive. So I do a search command:
find . -name "*.jdk"
But it doesn't find anything. Not even the one I know that I have. How come?

find . only looks in your current directory. If you have permissions to look for files in other directories (root access) then you can use the following to find your file -
find / -type f -name "*.jdk"
If you are getting tons of permission denied messages then you can suppress that by doing
find / -type f -name "*.jdk" 2> /dev/null

a/
find . means, "find (starting in the current directory)." If you want to search the whole system, use find /; to search under /System/Library, use find /System/Library, etc.
b/
It's safer to use single quotes around wildcards. If there are no files named *.jdk in the working directory when you run this, then find will get a command-line of:
find . -name *.jdk
If, however, you happen to have files junk.jdk and foo.jdk in the current directory when you run it, find will instead be started with:
find . -name junk.jdk foo.jdk
… which will (since there are two) confuse it, and cause it to error out. If you then delete foo.jdk and do the exact same thing again, you'd have
find . -name junk.jdk
…which would never find a file named (e.g.) 1.6.0.jdk.
What you probably want in this context, is
find /System -name '*.jdk'
…or, you can "escape" the * as:
find /System -name \*.jdk

Probably your JDKs are uppercase and/or the version of find available on OS X doesn't default to -print if no action is specified; try:
find . -iname "*.jdk" -print
(-iname is like -name but performs a case-insensitive match; -print says to find to print out the results)
--- EDIT ---
As noted by #Jaypal, obviously find . ... looks only into the current directory (and subdirectories), if you want to search the whole drive you have to specify / as search path.

The '.' you are using is the current directory. If you're starting in your home dir, it will probably miss the JDK files.
Worst case search is to start from root
find / -name '*.jdk' -o -name '*.JDK' -print
Otherwise replace '/' with some path you are certain should be parent to you JDK files.
I hope this helps.

If you are on Mac terminal, and also already in the directory where you want the search to be conducted at, then this may also work for you:
find *.pdf
At least it worked for me.

find / -type f -name "*.jdk" works on Mac also

This works for me on macOS.
find . -type f -iname '*.jdk'

ls *.jpg | cut -f 1 -d "."
sub out the '.jpg' to whatever extension you want to list

Related

bash, delete all files with a pattern name

I need to delete all files with a pattern name:  2020*.js
Inside a specific directory: server/db/migrations/
And then show what it have been deleted: `| xargs``
I'm trying this:
find . -name 'server/db/migrations/2020*.js' #-delete | xargs
But nothing is deleted, and shows nothing.
What I'm doing wrong?
The immediate problem is that -name only looks at the last component of the file name (so 2020xxx.js) and cannot match anything with a slash in it. You can use the -path predicate but the correct solution is to simply delete these files directly:
rm -v server/db/migrations/2020*.js
The find command is useful when you need to traverse subdirectories.
Also, piping the output from find to xargs does not do anything useful; if find prints the names by itself, xargs does not add any value, and if it doesn't, well, xargs can't do anything with an empty input.
If indeed you want to traverse subdirectories, try
find server/db/migrations/ -type f -name '2020*.js' -print -delete
If your shell supports ** you could equally use
rm -v server/db/migrations/**/2020*.js
which however has a robustness problem if there can be very many matching files (you get "command line too long"). In that scenario, probably fall back to find after all.
You're looking for something like this:
find server/db/migrations -type f -name '2020*.js' -delete -print
You have try this:
find . -name 'server/db/migrations/2020*.js' | xargs rm

Trying to find files containing an identifier, then move them to a new directory within terminal

I'm a beginner with this stuff and seem to be running into an issue.
Basically, I have many files with names containing a keyword (let's call it "Category1") within a directory. For example:
ABC-Category1-XYZ.txt
I'm trying to move them from a directory into another directory with the same name as the keyword.
I started with this:
find /path_A -name "*Category1*" -exec mv {} /path_A/Category1 \;
It spit out something like this:
mv: rename /path_A/Category1 to /path_A/Category1/Category1: Invalid
Argument
So I did some fiddling and hypothesized that the problem was caused by the command trying to move the directory Category1 into itself(maybe). I decided to exclude directories from the search so it would only attempt to move files. I came up with this:
find /path_A -name "*Category1*" \(! -type d \) -exec mv {} /path_A/Category1 \;
This did move the files from their original location to where I wanted them, but it still gave me something like:
mv: /path_A/Category1/ABC-Category1-XYZ.txt and
/path_A/Category1/ABC-Category1-XYZ.txt are identical
I'm no expert, so I could be wrong... but I believe the command is trying to find and move the files from their original directory, then find them again. The directory Category1 is a subdirectory of the starting point, /path_A, So i believe it is finding the files it just moved in the directory Category1 and attempting to move them again.
Can anyone help me fix this issue?
You are creating new files that find tries to process. Safest approach is to move them somewhere else not in the path_A you are searching with find.
Or you can use prune to ignore that directory if you don't have any other directory matching:
find /path_A -name '*Category1*' -prune -type f -exec mv {} /path_A/Category1/ \;
Although another post has been accepted, let me post a proper answer.
Would you please try:
find /path_A -name 'Category1' -prune -o -type f -name '*Category1*' -exec mv -- {} /path_A/Category1/ \;
The option -prune is rather a command than a condition. It tells find to
ignore the directory tree specified by the conditions before -prune.
In this case it excludes the directory Category1 from the search.
The following -o is logical OR and may be interpreted something like instead or else. The order of the options makes difference.
Please be noticed the 1st category1 is the directory name to exclude and the 2nd *Category1* is the filenames to find.
If you are not sure which files are the result of find, try to execute:
find /path_A -name 'Category1' -prune -o -type f -name '*Category1*' -print
then tweak the options to see the change of output.

Why can't I exclude a directory using find

I attempting to run a command on all subdirectories in a directory using find and -exec, however on one of the directories, the user the script runs under does not have adequate permissions and I get an error (permission denied). I am attempting to ignore the directory using either ! -path or using -prune. Neither of these methods work. I have tried both of the commands down below.
I have tried every combination of subDirToExclude— with and without ./ at the beginning, with and without /* at the end. I've tried relative path, full path and every single combination of all of them that you can think of to try and match this path, but it simply does not work. The man page is unhelpful and no suggestions from any related questions on this forum produce any useful results. Why do none of the methods suggested in the man page work? How can this actually be done?
find /path/to/dir -maxdepth 1 -type d ! -path "subDirToExclude" -exec somecommand {} +
find /path/to/dir -maxdepth 1 -type d -path "subDirToExclude" -prune -o -exec somecommand {} +
find: ‘/path/to/dir/subDirToExclude’: Permission denied
The argument to the -path option should be a full pathname, not just the name of the directory. Use -name if you just want to match the name of the directory.
find /path/to/dir -maxdepth 1 -type d ! -name "subDirToExclude" -exec somecommand {} +
You could also do this without using find at all, since you're not recursing into subdirectories because of -maxdepth 1.
shopt -s extglob
somecommand /path/to/dir /path/to/dir/!(subDirToExclude)/
Putting / at the end of the filename makes the wildcard only match directories. Actually, this will also match symbolic links to directories; if that's a problem, you can't use this solution.

Searching for exact file extension using sh or bash on macOS (syntax issue)

Looking for files with .pst or .pst extension. A few apps have files in their bundles that have either/both extensions, so excluding them.
After some testing, found this script works:
#!/bin/sh
find /Users -type f -not -path "*AnApplication.app*" | grep -i "*.pst$" > /path/to/search-result.txt
exit 0
However it is returning *.dpst" files. which I thought would not happen given the grep -i "*.pst$" part of the command.
We are using the $ to ensure search returns extensions, and not files with ".pst" in the path or middle of name (Example: myFile.pst.doc or /path/my.pst.files/).
Our goal is to find only files ending in ".pst", what am I doing rong? :)
Thanks for the huge help, my apologies for the belated response. Here is what we ended up going with:
find /Users -type f -not -path '*AnApplication.app*' -iname '*.pst'

get a list of files and directories with full path in unix

I am trying to get full path of both the files and directories from a directory. I tried using find but unable to get result.
when I used find /home/demo -type f it only lists files and find /home/demo -type d only lists directories.
Is there a way to get both using Find?
You can specify the absolute path of a directory. As an example for the current directory:
find "`pwd`"
pwd shows full path of current directory. ` ` summons a subshell in which output can be used as an argument to the command.
A literal example can be:
find /home/user
Update: You can use -o to explicitly target both files and directories. Doing find without an option may include other types besides the two.
find /home/user \( -type f -o -type d \)
Note: -or is synonymous but may not work in other versions of find since it's not POSIX compliant.

Resources