Linux find command: Comprehensive Guide

The find command in Linux is a powerful utility for searching and locating files and directories based on conditions you specify.

It can quickly locate files by name, size, type, permissions, date, and many other criteria.

 

 

Basic Syntax

The basic syntax for the find command is:

find [path...] [expression]
  • path: This is where you specify the directory to start the search from. For instance, you can start your search from the root directory (/) or from your home directory (~).
  • expression: This is the condition or criteria to match. For instance, you might search for files by name, size, type, and more.

Output:

$ find /home/user -name myfile.txt
/home/user/documents/myfile.txt

This searches the /home/user directory for a file named myfile.txt.

 

Finding Files by Name

Case-sensitive

You can use the -name option followed by the file name or pattern to search for files by name.

$ find /home/user -name notes.txt
/home/user/documents/notes.txt
/home/user/backups/notes.txt

This command checks the /home/user directory for all files named notes.txt.

Case-insensitive

If you want to perform a case-insensitive search, use the -iname option.

$ find /home/user -iname Notes.TXT
/home/user/documents/notes.txt
/home/user/backups/NOTES.txt

Here, the search retrieves files named ‘notes.txt’, ‘NOTES.TXT’, and any other variations in case.

 

Using Regular Expressions

find can also match files based on regular expressions, providing a more flexible search pattern.

Using the -regex

The -regex option searches based on the full path of the file.

$ find /home/user -regex "/home/user/docs/.*\.txt$"
/home/user/docs/report.txt
/home/user/docs/summary.txt

This command retrieves all .txt files inside the /home/user/docs directory.

Using the -iregex

To perform a case-insensitive regex search, use the -iregex option.

$ find /home/user -iregex "/home/user/DOCS/.*\.txt$"
/home/user/docs/report.txt
/home/user/DOCS/Overview.TXT

This returns .txt files from both /home/user/docs and /home/user/DOCS directories, regardless of the case.

Read more on how to use regex with Linux find command.

 

Finding Files by Type

You can use the -type option followed by a specific code to indicate the file type to search for files based on their type.

To search for regular files, you can use f code:

$ find /home/user -type f
/home/user/file1.txt
/home/user/image.png

This lists all regular files in the /home/user directory.

To search for directories, you can use d code:

$ find /home/user -type d
/home/user/documents
/home/user/pictures

This command returns all directories in the /home/user directory.

To search for symbolic links, you can use the l code:

$ find /home/user -type l
/home/user/link_to_file1.txt

This lists all symbolic links in /home/user.

Other file types:

  • b: block device files
  • c: character device files
  • p: named pipes (FIFOs)
  • s: socket files

For example, to find all block device files:

$ find / -type b
/dev/sda
/dev/sdb

This retrieves all block devices in the system.

 

Finding Files by Size

To search for files based on their size, you can use the -size option.

$ find /home/user -size +2M
/home/user/movies/sample.mp4
/home/user/backups/backup.tar.gz

This command lists files in the /home/user directory that are larger than 2 Megabytes.

Understanding size format

The size criteria can be specified using various formats:

  • c: bytes
  • k: kilobytes
  • M: megabytes
  • G: gigabytes

The symbol before the size unit indicates the condition:

  • +: greater than the specified size
  • -: less than the specified size
  • (no symbol): exactly the specified size
$ find /home/user -size -10k
/home/user/notes.txt
/home/user/config.yaml

This finds files in /home/user that are smaller than 10 kilobytes.

 

Find Empty Files or Directories

The -empty option allows you to locate empty files or directories.

$ find /home/user -type f -empty
/home/user/emptyfile.txt
/home/user/drafts/untitled.doc

This command lists all empty regular files in the /home/user directory.

To find empty directories:

$ find /home/user -type d -empty
/home/user/drafts/unused_folder

This returns all empty directories within /home/user.

 

Finding Files by Date and Time

There are several options you can use with find command to search for files by access date/time or modification date/time.

Search by access time

You can use the -amin option to search for files accessed in the specified number of minutes.

$ find /home/user -amin -10
/home/user/documents/recently_opened.txt

This command retrieves files in /home/user accessed within the last 10 minutes.

You can use the -atime option to search for files accessed in the past ‘n’ days.

$ find /home/user -atime -7
/home/user/documents/week_report.txt

This locates files in /home/user accessed within the past week.

Search by inode change

You can use -cmin option to search for files based on inode change time in minutes.

inode includes changes to the file’s metadata, such as its permissions or ownership, but not necessarily its content.

$ find /home/user -cmin -30
/home/user/configs/changed_config.cfg

This command finds files in /home/user that had their inode changed within the last 30 minutes.

You can use the -ctime option to search for files based on inode change time in days.

$ find /home/user -ctime -2
/home/user/configs/recently_changed_config.cfg

This locates files in /home/user that had their inode changed within the past 2 days.

Search by modification time

You can use the -mmin option to search for files based on modification time in minutes.

$ find /home/user -mmin -15
/home/user/documents/just_edited.txt

This finds files in /home/user that were modified within the last 15 minutes.

To search for files based on modification time in days, you can use the -mtime option:

$ find /home/user -mtime -3
/home/user/documents/three_days_ago_edited.txt

This returns files in /home/user that were modified within the past 3 days.

Find newer files

You can use the -newer option to find files that are newer than a given file.

$ find /home/user -newer reference.txt
/home/user/documents/updated_report.txt

This lists files in /home/user that are newer than reference.txt.

Compare timestamps using -newerXY

The -newerXY option lets you compare the timestamp of files against another file or a specific time. The X and Y can be:

  • a: Access time
  • m: Modification time
  • c: Inode change time
  • t: Literal time (specified directly)

For example, to find files modified more recently than they were accessed:

$ find /home/user -neweram reference.txt
/home/user/documents/recently_edited_but_not_opened.txt

This command lists files in /home/user that have a more recent modification time than their access time compared to reference.txt.

To compare against a specific date, you can use:

$ find /home/user -newermt "2023-08-18"
/home/user/documents/post_august_file.txt

This finds files in /home/user that were modified after August 18, 2023.

Files accessed after modification

The -used option allows you to search for files based on the number of days between the file’s last access and last modification.

$ find /home/user -used +7
/home/user/old_drafts/draft1.txt

This command lists files in /home/user that were last accessed more than 7 days after their last modification. Such files might have been modified and then left untouched for a while.

Remember, this doesn’t show you files based on their last accessed time or their modification time directly; rather, it’s showing you files based on the difference in days between those two times.

 

Finding Files by Permissions

The -perm option lets you search for files based on their permissions.

$ find /home/user -perm 0755
/home/user/scripts/executable_script.sh

This command lists files in /home/user with permissions set to 0755.

You can also use symbolic representation:

$ find /home/user -perm u=rwx,g=rx,o=rx
/home/user/scripts/executable_script.sh

This retrieves the same files as the previous command but uses symbolic notation for permissions.

For permissions that match any of the given modes:

$ find /home/user -perm -o=w
/home/user/shared/shared_file.txt

This finds files in /home/user where others have write permission.

 

Searching for Files with Special Permissions

You can use the -perm option combined with specific codes to search for files with special permissions, such as the sticky bit, setuid, and setgid.

Sticky Bit

You can use the -1000 code to search for files with the sticky bit set will have the t in their permissions.

$ find /home/user -perm -1000
/home/user/shared_directory

This finds directories in /home/user with the sticky bit set.

Setuid

To search for files with the setuid bit set will have the s in the user’s execute permission, you can use the -4000 code.

$ find /home/user -perm -4000
/home/user/bin/setuid_program

This lists files in /home/user with the setuid bit set.

Setgid

You can use the -2000 code to search for files with the setgid bit set will have the s in the group’s execute permission.

$ find /home/user -perm -2000
/home/user/bin/setgid_program

This returns files in /home/user with the setgid bit set.

 

Searching by User and Group

To search files based on ownership, you can use the following options:

-user

You can use the -user option to search for files owned by a specific user.

$ find /home/user -user john
/home/user/johns_file.txt

This lists files in /home/user owned by the user john.

-group

You can use the -group option to search for files belonging to a particular group.

$ find /home/user -group developers
/home/user/dev/project1.txt

This retrieves files in /home/user that belong to the developers group.

-nouser

You can use the -nouser option to find files that do not have a valid user associated with them.

$ find / -nouser
/orphaned_files/file1.txt

This lists files without a valid user owner in the root directory.

-nogroup

You can use the -nogroup option to find files that do not belong to any valid group.

$ find / -nogroup
/orphaned_files/file2.txt

This locates files without a valid group in the root directory.

 

Exclude Directories

If you need to exclude certain directories from your search, you can use the -prune option.

$ find /home/user -path '/home/user/excluded_directory' -prune -o -print
/home/user/file1.txt
/home/user/other_directory/file2.txt

Here, the search avoids the excluded_directory while printing other results from /home/user.

Remember: order matters with -prune. Ensure you specify what to prune before the -o -print part, or you’ll get unexpected results.

 

Search for hard links to file

The -samefile option helps you search for files that point to the same inode as a specified file, essentially finding hard links to that file.

$ find /home/user -samefile /home/user/reference.txt
/home/user/reference.txt
/home/user/links/reference_hardlink.txt

This command identifies all files in /home/user that point to the same inode as reference.txt, which in this case includes the original file and its hard link.

 

Combining Multiple Search Criteria

Sometimes, you’ll need to search based on multiple conditions. The find command is flexible enough to combine various search criteria.

Combining Conditions

To find .txt files modified within the last 3 days:

$ find /home/user -name "*.txt" -mtime -3
/home/user/recently_edited.txt

Using -o (OR)

To search for .txt or .md files:

$ find /home/user -name "*.txt" -o -name "*.md"
/home/user/note.txt
/home/user/readme.md

Using -a (AND)

While -a is the default, if you want to be explicit, you can use it to combine conditions.

To find .txt files modified in the last 3 days and larger than 1k:

$ find /home/user -name "*.txt" -a -mtime -3 -a -size +1k
/home/user/large_recently_edited.txt

Using ! (NOT)

You can use ! to negate the condition of the search.

To find files that are not .txt:

$ find /home/user ! -name "*.txt"
/home/user/image.jpg

This returns all files in /home/user that do not have the .txt extension.

 

Limiting Search Depth

There are times when you may want to limit the depth of your search. This is where -maxdepth and -mindepth come into play.

maxdepth

The -maxdepth limits the depth of the directory traversal.

$ find /home/user -maxdepth 1 -name "*.txt"
/home/user/file1.txt

This finds .txt files in /home/user but does not search in subdirectories.

mindepth

The -mindepth specifies the minimum depth of the directory traversal.

$ find /home/user -mindepth 2 -name "*.txt"
/home/user/subdir/file2.txt

This searches for .txt files in /home/user but only starting from the second level of directories.

 

Executing Commands on Files Found

You can take action on the results directly.

Using -exec

The -exec option allows you to run a command on each found item.

$ find /home/user -name "*.txt" -exec cp {} /home/backup/ \;

This command finds all .txt files in /home/user and copies them to the /home/backup/ directory.

Using the -execdir

Similar to -exec, but executes the specified command in the directory where the matched file resides.

$ find /home/user -name "config.cfg" -execdir mv {} {}.backup \;

This renames all config.cfg files found in /home/user to config.cfg.backup.

Safe Executions with {} + and {} ;

Using {} + allows multiple file names to be passed as arguments at once.

$ find /home/user -name "*.txt" -exec echo {} +
/home/user/file1.txt /home/user/file2.txt

Using {} \; ensures that the command is executed for each file separately.

$ find /home/user -name "*.txt" -exec echo {} \;
/home/user/file1.txt
/home/user/file2.txt

Using -delete

The -delete action enables you to remove files or directories that match your search criteria.

$ find /home/user -name "*.tmp" -delete

The -delete action processes deletions depth-first, so directories will be emptied of files before the directory itself is removed. This is crucial when working on directories.

Using -delete can result in data loss. That’s why you need confirmation such as the -ok action provides.

Confirm action (using -ok)

The -ok action in the find command serves as a safeguard when executing commands on found files.

$ find /home/user -name "*.bak" -ok rm {} \;
< rm ... /home/user/documents/file1.bak > ? y
< rm ... /home/user/documents/file2.bak > ? n

For each file, find prompts you with the full command it intends to execute (e.g., < rm ... /home/user/documents/file1.bak > ?).

You must answer with ‘y’ (yes) or ‘n’ (no) for each file. Only files confirmed with ‘y’ are processed.

Using -okdir

Just like -ok, it prompts the user for confirmation before executing a command.

However, -okdir executes the specified command from the directory containing the matched file, making it safer for commands that might have unintended consequences if executed with an incorrect path.

$ find /home/user -name "*.bak" -okdir rm {} \;
< rm ... file1.bak > ? y
< rm ... file2.bak > ? n

Unlike -ok, which shows the full path, -okdir shows the filename because the command is executed in the file’s directory.

-ok vs. -okdir

When using -ok, the command you’re executing is run from the directory where you invoked the find command. The {} placeholder will be replaced by the entire path to the matched file.

In contrast, when you use -okdir, the command is run from the directory containing the matched file, and the {} placeholder will be replaced by the base name of the matched file (i.e., without the preceding directory path).

So, -okdir adds a layer of safety.

 

Using Find with Xargs

xargs is a powerful tool that reads items from standard input and executes a command on them.

It’s often used with find to handle filenames and other input.

$ find /home/user -name "*.txt" | xargs tar cvf backup.tar
backup.tar
/home/user/file1.txt
/home/user/file2.txt

This command packs all .txt files found in /home/user into a backup.tar archive.

For filenames with spaces or special characters, it’s safer to use:

$ find /home/user -name "*.txt" -print0 | xargs -0 tar cvf backup.tar

Here, -print0 in find and -0 in xargs ensure filenames are treated correctly, even if they contain spaces, newlines, or other special characters.

 

Handling Files with Special Characters

When working with filenames that contain special characters, like spaces or parentheses, you must ensure they’re handled correctly.

$ find /home/user -name "my file*.txt"
/home/user/my file1.txt
/home/user/my file2.txt

If you’re scripting or chaining commands, quote the patterns:

$ find /home/user -name "my file*.txt" -exec cat '{}' \;
Contents of my file1.txt
Contents of my file2.txt

By wrapping {} in single quotes, you ensure filenames with special characters get passed to the cat command without issues.

 

Using the -sparse

The -sparse option identifies files that are sparsely allocated. Sparse files consume less actual space on disk than their apparent size might suggest.

$ find /home/user -sparse
/home/user/large_but_sparse_file.img

This finds files in /home/user that are sparse. Typically, these files have blocks that read as zero, but don’t consume any space on disk.

 

Printing Results

By default, find prints the names of files that meet the specified conditions. However, there are more elaborate methods to print results.

Print file names

The -print option allows you to prints the full file name.

$ find /home/user -name "sample.txt"
/home/user/documents/sample.txt

Format output

The -printf option allows custom formatting of the output.

$ find /home/user -name "sample.txt" -printf "%f %s bytes\n"
sample.txt 1240 bytes

This prints just the filename (%f) and its size in bytes (%s), followed by the word “bytes”.

detailed listing

The -ls option provides a detailed listing similar to ls -l.

$ find /home/user -name "sample.txt" -ls
1234567  4 -rw-r--r-- 1 user user 1240 Aug 16 12:30 /home/user/documents/sample.txt

The output displays the inode number, size in blocks, file permissions, number of links, owner, group, size in bytes, modification time, and the file name.

 

Search specific mounted devices (-xdev or -mount)

When working with large filesystems or multiple mount points, limiting the search to a specific filesystem can improve the find command’s performance.

Both -xdev and -mount are the same option, just with different names. This option prevents find from descending into directories that reside on different file systems (or partitions).

This can be useful if you’re searching a directory like / (root) but you don’t want to search other mounted filesystems like /boot or /home if they’re on separate partitions or devices.

Example: Let’s say you want to find all the .log files in the /var directory but not go into other mounted file systems:

$ find /var -xdev -name "*.log"

In this example, if /var/log was a separate mount point or on a different partition, -xdev or -mount would prevent find from searching within /var/log.

Note: It’s important to place the -xdev or -mount option before any predicates like -name to ensure it’s treated as an option.

 

The Power of Find Command

One day, I received an urgent call from the head of the customer service department. They informed me that many customers had reported not receiving their monthly statements.

I quickly pulled up the logs and realized there were over 100,000 files, spread across multiple directories and subdirectories, which contained these statements.

The main issue was that a substantial portion of these files was misnamed, and because of this naming inconsistency, they couldn’t be sent out to the respective customers.

Had this been a manual task, it would have been a disaster. Going through 100,000 files, even with a sizable team, would have taken days if not weeks.

Let’s say, for argument’s sake, that a person could handle 100 files an hour. With eight working hours in a day, that’s 800 files.

To cover 100,000 files, it would require 125 man-days. Even with a team of 10 people, we’d be looking at almost two weeks of work.

This is where the magic of Linux’s find command came in.

I used a simple command:

$ find /path_to_directory/ -type f -name "wrong_pattern_*"

In no time, it gave me a list of all the misnamed files, regardless of their directory depth. Using the same command, I combined it with a rename operation:

$ find /path_to_directory/ -type f -name "wrong_pattern_*" -exec rename 's/wrong_pattern_/correct_pattern_/' '{}' \;

Within a matter of minutes, all the misnamed files were correctly renamed.

The batch process that sent out the statements was rerun, and within a couple of hours, all the statements were dispatched correctly.

 

Resource

https://man7.org/linux/man-pages/man1/find.1.html

4 thoughts on “Linux find command: Comprehensive Guide
  1. Hi good examples
    In the last combined example of nice & ionice, in the nice -n , the value is missing.

Leave a Reply

Your email address will not be published. Required fields are marked *