bash find - ghdrako/doc_snipets GitHub Wiki

  • -name case-sensitive searches
  • -iname case-insensitive searches
sudo find / -iname '*.conf' -mtime -7 -ls 
find / -path */doc/* -path */bash/*
find / -path */doc/* -a -path */bash/*

-a option between conditions means logical AND. If you do not specify any logical operator between conditions, find inserts AND by default. This is a reason why both calls provide the same result.

find / -mount -path */doc/* -a -path */bash/*

The -mount option exclude mount points from the search.

find / \( -path */doc/* -name README \) -o -name LICENSE

-o means logical OR

find . -type d  # find only directory
find . -size +1M # find all files larger than 1MB in the current directory
find . -mtime -7 #  find all files modified in the last 7 days in the current directory

Finding files

The find command searches a directory and its subdirectories by default

find​​ ​​~/Desktop​​ ​​-name​​ ​​"greetings.txt"​
find​​ ​​~/Desktop​​ ​​-name​​ ​​"gr*.txt"​  
find​​ ​​~/Desktop​​ ​​-name​​ ​​"GR*.txt"   # -name argument is case-sensitive
find​​ ​​~/Desktop​​ ​​-iname​​ ​​"GR*.txt"​ #  -iname find anything that matches, regardless of case
find​​ ​​/var/log​​ ​​-mmin​​ ​​-30​         # files that changed in the last 30 minutes

Using a minus sign in front of the number makes the search look for files from the current time backward to the specified number of minutes. If you leave the minus sign off, you’d be looking for files that changed exactly that many minutes ago. If you used a plus sign, you’d be looking for things that changed more than 30 minutes ago.

find​​ ​​/var/log​​ ​​-mmin​​ ​​-30​​ ​​-ls​  # -ls show files attributes
​​find​​ ​​/var/log​​ ​​-mmin​​ ​​-30​​ ​​-exec​​ ​​ls​​ ​​-ldh​​ ​​{}​​ ​​\;​ # -d switch tells ls to treat a directory as a file rather than listing its contents
                                            # {} is a placeholder for the file that gets passed to the program
                                            # \; at the end tells find to run the command on each file it finds.
find​​ ​​/var/log​​ ​​-mmin​​ ​​-30​​ ​​-exec​​ ​​ls​​ ​​-ldh​​ ​​{}​​ ​​+​  # +, the find command will attempt to group the arguments into a single call. 
                                            # This can be more efficient
                                            # ls command runs only once, instead of once for each file in the list
Option Meaning Example
-exec command {} \; Execute the specified command on each found object. find -name README -type f -exec cp {} ∼ ;
-exec command {} + Execute the specified command once over all found objects. The command receives all these objects on the input. find -type d -exec cp -t ∼ {} +
-delete Delete each of the found files. Thebutility deletes empty directories only.

Find difference between dirs

# Files that are in both Dir1 and Dir2:
find "$Dir1/" "$Dir2/" -printf '%P\n' | sort | uniq -d

# Files that are in Dir1 but not in Dir2:
find "$Dir1/" "$Dir2/" "$Dir2/" -printf '%P\n' | sort | uniq -u

# Files that are in Dir2 but not in Dir1:
find "$Dir1/" "$Dir1/" "$Dir2/" -printf '%P\n' | sort | uniq -u

I had a special case where I wanted to compare Dir1 and Dir2, but Dir2 is a subfolder of Dir1. In that case I needed to exclude the output of Dir2 in Dir1. This is what I used to find Files that are in Dir1 but not in Dir2:

(find . -printf '%P\n' | grep -v Dir2  && find Dir2/ -printf '%P\n' && find Dir2/ -printf '%P\n') | sort | uniq -u

It assumes I am already inside Dir1

Proces find files

find . -name "*.txt"|while read fname; do
  echo "$fname"
done

The -print0 will use the NULL as a file separator instead of a newline and the -d $'\0' will use NULL as the separator while reading.

find . -name "*.txt" -print0 | while read -d $'\0' file
do
    …code using "$file"
done