Find notes

Notes on the Linux find command.

Index

Find multiple file names

find ~ -type f -name "foo" -o -name "bar"

-o acts as an OR condition.

Find ignoring a file

In this example excluding todo.txt prevents an infinate loop that would otherwise result in todo.txt growing to fill all space on the hard disk.

find . -type f \( -name "*.txt" ! -name "todo.txt" \) -exec grep "TODO" -iHn {} \; > todo.txt

This will search for ‘TODO’ or ‘todo’ in all .txt files except todo.txt and write the output to todo.txt (hence why it’s ignored).

Beware of spaces. There must be spaces between the escaped brackets and the arguments. E.g:

steph@bpc ~ $ find . -type f \(-name "*.txt" ! -name "todo.txt" \) -exec grep "TODO" -iHn {} \; > todo.txt
find: paths must precede expression: (-name
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

Find ignoring a file and a directory

find . -path "./tmp/*" -prune -o \( -name "*.txt" ! -name "todo.txt" \) -print > todo.txt

This is similar to the earlier examples except also ignores files in the tmp directory.

-prune is carried out if the path is matched, removing them from the results. -o is an OR condition. Everything after this is carried out when the path isn’t matched.

So we’re exluding the directory, then excluding the todo.txt file (as per the earlier example).

Find files with particular permissions

Find all files in /home/steph that are readable for other users:

find /home/steph -perm -o=r

Find all files in /home/steph that are readable or writeable (or both) for the group or others (or both):

find /home/steph -perm +go=rw

Reference: CLI Magic: Searching with find

Find files not owned by a particular user or group

To find files below the current directory not owned by particular user, use the following command (in this example the user is called steph):

find . \! -user steph -print

You can do the same with groups:

find . \! -group steph -print

Reference: Looking for Files NOT owned by someone

Change extension of multiple files

To change the extension of multiple files, e.g. rename .html.bak to .html:

find . -type f -name "*.html.bak" -exec sh -c 'mv {} `basename "{}" .bak`' \;

Dealing with spaces when using find with exec

To prevent problems with spaces in filenames when running the ‘find’ command with -exec, use double quotes:

find . -type f -name "*.html" -exec grep ls "{}" \;

Find files excluding a directory

Find files that contain ‘foo’, excluding those in ‘media’ directory:

find . -type f ! -path "./media/*" -exec grep "foo" -Hn {} \;

Find files that contain ‘foo’, excluding those in ‘media’ and ‘cache’ directories:

find . -type f ! -path "./media/*" ! -path "./cache/*" -exec grep "foo" -Hn {} \;

Prune

Alternatively you can use the -prune options…

Find files that contain ‘foo’, excluding those in the ‘media’ directory:

find . -path "./media/*" -prune -o -type f -exec grep "foo" -Hn {} \;

Find files that contain ‘foo’, excluding those in the ‘media’ and ‘cache’ directories:

find . -type d \( -path "./media/*" -o -path "./cache/*" \) -prune -o -type f -exec grep "foo" -Hn {} \;

References

Find with nested commands

If you want to run nested commands on the results of a ‘find’, then you’ll have to stop bash expansion running before the find command.

E.g. This won’t work because the shell expansion will happen before the find has set the {} to the filename:

find . -type f -name "*.html.bak6" -exec mv {} `basename "{}" .bak6` \;

This will work because the shell expansion will happen after {} is populated:

find . -type f -name "*.html.bak6" -exec sh -c 'mv {} `basename "{}" .bak6`' \;

Last modified: 15/12/2014 Tags: ,

Related Pages

Other pages possibly of interest:

This website is a personal resource. Nothing here is guaranteed correct or complete, so use at your own risk and try not to delete the Internet. -Stephan

Site Info

Privacy policy

Go to top