Date created: 08/30/20 19:34:34. Last modified: 03/02/21 14:14:57

'find' - Notes

Find by name and type:

# Files that don't end in ".mp3" or ".wav":
find . -not name "*.mp3" -not -name "*.wav" -type f
# Directories which contain "foo" in the name, case insensitive:
find . -iname "*foo*" -type d


Find by size:

# 70MBs and larger
find . -type f -size +70M

du -h -d 1 | sort -hr


Find and delete:

# Delete Mac OS .DS_Store and ._.DS_Store files

# Using "\;" calls rm for every file found
find . -name "*.DS_Store" -exec rm {} \;

# Using "+" calls rm once with all file names as arguments to speed up the process
find . -name "*.DS_Store" -exec rm {} +

# If files have spaces in the name/path, find can delete them using the -delete option because the spaces will cause -exec rm will fail
find . -name "*.DS_Store" -delete



-exec runs the command from the current folder where find is being executed from.

-execdir run the command in the file where the found file is located.

# Recursively unrar archives in multiple sub-folders
find . -name '*.rar' -execdir unrar e {} \;


Exec with basename and renaming:

# -execdir executes the command inside the directory of the file returned by find, in the directory find is being run from:
find . -name "*.m4a" -execdir sh -c 'x="`basename \"{}\" .m4a`"; cp "$x".m4a "$x".copy' \;

# Convert files ending in m4a to mp3, using basename to get the original filename:
find . -iname "*.m4a" -execdir sh -c 'x="`basename \"{}\" .m4a`"; ffmpeg -i "$x".m4a -acodec libmp3lame -ab 320k "$x".mp3' \;

# Bash has a built-in string substitution feature which is less clunky than using basename:
ls *.m4a
aaa.m4a bbb.m4a ccc.m4a

find . -name "*.m4a" -execdir bash -c 'a="{}"; cp "$a" "${a/m4a/copy}"' \;

aaa.copy aaa.m4a bbb.copy bbb.m4a ccc.copy ccc.m4a


Exec with escaping:

# Find files with a backslash in the name and use the -exec argument to launch a bash shell to rename the files
find . -name "*\\\*" -exec bash -c 'x="{}"; y="$(sed "s/\\\/-/g" <<< "$x")" && mv "$x" "$y" ' \;



# When working with external commands find output can be piped to xargs verbatim...
find . -name "*.DS_Store" | xargs ...

# Or use -print to print each file/path separated by a new line
find . -name "*.DS_Store" -print0 | xargs ...
# or -print0 to print each file/path separated by a null character
find . -name "*.DS_Store" -print0 | xargs --null ...

find . -name "*.DS_Store" -print0 | xargs --null -I{} echo "Filename is {}" \;


Previous page: 'dig' - Notes
Next page: HTTP Servers