The -exec parameter holds the real power. When a file is found that matches the search criteria, the -exec parameter defines what to do with the file. This example tells the computer to:
1. Search from the current directory on down, using the dot (.) just after find.
2. Locate all files that have a name ending in .gif (graphic files).
3. List all found files, using the ls command.
The -exec parameter requires further scrutiny. When a filename is found that matches the search criteria, the find command executes the ls {} string, substituting the filename and path for the {} text. If saturn.gif was found in the search, find would execute this command:
$ ls ./gif_files/space/solar_system/saturn.gif
An important alternative to the -exec parameter is -ok; it behaves the same as -exec, but it prompts you to see if you want to run the command on that file. Suppose you want to remove most of the .txt files in your home directory, but you wish to do it on a file-by-file basis. Delete operations like the UNIX rm command are dangerous, because it's possible to inadvertently delete files that are important when they're found by an automated process like find; you might want to scrutinize all the files the system finds before removing them.
The following command lists all the .txt files in your home directory. To delete the files, you must enter Y or y when the find command prompts you for action by listing the filename:
$ find $HOME/. -name *.txt -ok rm {} \;
Each file found is listed, and the system pauses for you to enter Y or y. If you press the Enter key, the system won't delete the file.
If too many files are involved for you to spend time with the -ok parameter, a good rule of thumb is to run the find command with -exec to list the files that would be deleted; then, after examining the list to be sure no important files will be deleted, run the command again, replacing ls with rm.
Both -exec and -ok are useful, and you must decide which works best for you in your current situation. Remember, safety first!
Examples:
- To remove all temp, swap and core files in the current directory.
- To copy the entire contents of a directory while preserving the permissions, times, and ownership of every file and subdirectory
$ find . | cpio -vdump /path/to/destination/dir
- To list the first line in every text file in your home directory
$ less <>
- To maintain LOG and TMP file storage space for applications that generate a lot of these files, you can put the following commands into a cron job that runs daily:
- The first command runs all the directories (-type d) found in the $LOGDIR directory wherein a file's data has been modified within the last 24 hours (-mtime +0) and compresses them (compress -r {}) to save disk space. The second command deletes them (rm -f {}) if they are more than a work-week old (-mtime +5), to increase the free space on the disk. In this way, the cron job automatically keeps the directories for a window of time that you specify.
$ find $LOGDIR -type d -mtime +5 -exec rm -f {} \;
- To find links that point to nothing
- To list zero-length files
- To delete all *.tmp files in the home directory
(or)
$ find ~/. -name "*.tmp" -exec rm {} \;
- To see what hidden files in your home directory changed in the last 5 days:
- If you know something has changed much more recently than that, say in the last 14 minutes, and want to know what it was there's the mmin argument:
- To locate files that have been modified since some arbitrary date use this little trick:
$ find . -newer date_marker
- To find files created before that date, use the cnewer and negation conditions:
- To find files containing between 600 to 700 characters, inclusive.
Thus we can use find to list files of a certain size:
$ find /usr/bin -size 48k
- To find empty files
- Using the -empty argument is more efficient. To delete empty files in the current directory:
- To locate files belonging to a certain user:
- To search for files by the numerical group ID use the -gid argument:
- To find directories with '_of_' in their name we'd use:
- To redirect the error messages to /dev/null
- To remove all files named core from your system.
# find / -name core -exec /bin/rm -f '{}' \; # same thing
# find / -name core -delete # same if using Gnu find
- To find files modified less than 10 minutes ago. I use this right after using some system administration tool, to learn which files got changed by that tool:
# find / -mmin -10
- When specifying time with find options such as -mmin (minutes) or -mtime (24 hour periods, starting from now), you can specify a number n to mean exactly n, -n to mean less than n, and +n to mean more than n. 2 For example:
# find . -mtime 0 # find files modified within the past 24 hours
# find . -mtime -1 # find files modified within the past 24 hours
# find . -mtime 1 # find files modified between 24 and 48 hours ago
# find . -mtime +1 # find files modified more than 48 hours ago
# find . -mmin +5 -mmin -10 # find files modifed between 6 and 9 minutes ago
- To find all files containing “house” in the name that are newer than two days and are larger than 10K, try this:
# find . -name “*house*” -size +10240 -mtime -2
- The -xdev prevents the file “scan” from going to another disk volume (refusing to cross mount points, for example). Thus, you can look for all regular directories on the current disk from a starting point like this:
# find /var/tmp -xdev -type d -print
- To find world writables in your system:
# find / -perm 777 | xargs ls -ld | grep -v ^l | grep -v ^s
# find / -perm 666 | xargs ls -ld | grep -v ^l | grep -v ^s
# find . -perm +o=w -exec ls -ld {} \; | grep -v ^l | grep -v ^s | grep -v ^c
or
# find . -perm +o=w | xargs ls -ld | grep -v ^l | grep -v ^s | grep -v ^c
- To find the orphan files and directories in your system:
# find / -nouser -nogroup | xargs ls -ld
- To find the files changed in last 5 mins and move them to a different folder.
# find /tmp -mmin -5 -type f -exec mv {} /home/lokams \;
(or)
# mv `find . -mmin -5 -type f` /tmp/
(or)
# find . -mmin -10 -type f | xargs -t -i {} mv {} /tmp/
- To search on multiple directories
$ find /var /etc /usr -type f -user root -perm 644 -name '*ssh*'
- To find and list all regular files set SUID to root (or anyone else with UID 0 ;)
- To find all regular files that are world-writable and removes world-writability:
- To find all files owned by no one in particular and give them to root:
- To find all files without group ownership and give them to the system group:
- To find and gzip regular files in current directory that do not end in .gz
- To find all empty files in my home directory and delete after being prompted:
- To find all files or symlinks in /usr not named fred:
- If you have a file with spaces, control characters, leading hyphens or other nastiness and you want to delete it, here's how find can help. Forget the filename, use the inumber instead. Say we have a file named "-rf .", spaces and all. We wouldn't dare attempt removing it the normal way for fear of issuing 'rm -rf /' at the command line.
$ echo jhjhg > "-rf /"
$ ls -la
total 4
-rw-r----- 1 mongoose staff 6 Nov 07 15:57 -rf /
drwxr-x--- 2 mongoose staff 512 Nov 07 15:57 .
drwxr-xr-x 3 mongoose bin 1024 Nov 07 15:53 ..
Find the I-number of the file using the -i flag in ls:
$ ls -lai .
total 4
18731 -rw-r----- 1 mongoose staff 6 Nov 07 15:57 -rf .
18730 drwxr-x--- 2 mongoose staff 512 Nov 07 15:57 .
1135 drwxr-xr-x 3 mongoose bin 1024 Nov 07 15:53 ..
^^^^^
There it is: I-node 18731. Now plug it into find and make find delete it:
$ find . -inum 18731 -ok rm {} \;
rm ./-rf . (?) y
$ ls -la
total 3
drwxr-x--- 2 mongoose staff 512 Nov 07 16:03 .
drwxr-xr-x 3 mongoose bin 1024 Nov 07 15:53 ..