How to Use find -exec in Linux (With Examples)

Last updated Tuesday, February 3, 2026 11:32 am Joshua James 11 min read

The find -exec option turns file searches into automated batch operations. Instead of manually processing files one by one, you define search criteria and an action, then find handles everything from backing up photos spread across nested directories to compressing logs older than 30 days or adding watermarks to hundreds of images at once.

This guide covers the core syntax, explains the difference between single-file execution (\;) and batched execution (+), and walks through practical examples including backups, bulk renaming, format conversion, remote syncing, and automated reporting. You will also learn when to use -execdir for safer operations in the matched directory, and how to preview destructive commands before running them. Pair this with our chmod command guide when you need to modify permissions in bulk, or our grep command guide for searching file contents.

Understand the find -exec Command

What find -exec Does

If find -exec is new to you, think of it as a command-line automation assistant that scouts for files matching your criteria and then runs a specific action on each one. The find command locates files based on name patterns, modification times, sizes, or permissions. The -exec option extends that by letting you process each match immediately without piping to xargs or writing a loop.

Syntax Breakdown

The basic structure combines find’s search capabilities with command execution:

find [path] [expression] -exec [command] {} \;
  • [path]: Where to start searching. Use /var/log to scan log directories, . for the current directory, or ~ for your home folder.
  • [expression]: What to search for. Examples: -name "*.txt" finds text files, -mtime +30 finds files older than 30 days, -size +100M finds files larger than 100 megabytes.
  • -exec [command]: The action to perform on each match. Use ls -lh to list details, cp to copy, gzip to compress, or any command you would normally run manually.
  • {}: Placeholder replaced by each file’s full path. Every time find matches a file, it substitutes the actual filename here.
  • \;: Marks the end of the -exec command. The backslash escapes the semicolon so your shell does not interpret it prematurely.
  • +: Alternative terminator that batches multiple files into a single command invocation. Use -exec ls -la {} + instead of \; when processing many files with read-only commands like ls or grep to reduce overhead.

Understanding -exec vs -execdir

The -execdir option works like -exec but runs the command from the directory containing the matched file, not from where you invoked find. This matters for security and for commands that depend on relative paths.

With -exec, the {} placeholder contains the full path (e.g., /var/log/app/error.log). With -execdir, find changes to /var/log/app/ first, then {} contains just ./error.log. This prevents path-based exploits where a malicious filename could trick the command into operating on unintended files.

Use -execdir when:

  • Moving or renaming files to locations relative to their current directory
  • Running commands that expect to operate in the same directory as the file
  • Processing untrusted filenames where path injection is a concern

Simple Example First

At its simplest, find -exec runs a command on every match. To list detailed information for all PDF files in your Documents folder:

find ~/Documents -name "*.pdf" -exec ls -lh {} \;

This searches ~/Documents, finds every file ending in .pdf, and runs ls -lh on each one. You see one line of output per PDF showing the size, permissions, and modification date:

-rw-r--r-- 1 user user 2.4M Jan 15 10:30 /home/user/Documents/report.pdf
-rw-r--r-- 1 user user 156K Jan 12 08:15 /home/user/Documents/notes.pdf

Common find -exec Patterns by Task

The following table organizes typical find -exec scenarios by what you want to accomplish:

TaskExpression & CommandWhat It Does
Back up files-name "*.jpg" -exec cp {} {}.backup \;Creates a .backup copy of every .jpg file found
Delete old logs-name "*.log" -mtime +30 -exec rm {} \;Removes log files older than 30 days
Compress files-name "*.txt" -exec gzip {} \;Compresses each text file with gzip
Change permissions-type f -name "*.sh" -exec chmod +x {} \;Makes all shell scripts executable
Move files-type f -name "*.tmp" -execdir sh -c 'mkdir -p ./archive && mv "$1" ./archive/' _ {} \;Moves temporary files into an archive subdirectory created alongside each match
Display file details-name "*.conf" -exec ls -lh {} \;Shows size and permissions for config files
Rename files-name "*.html" -exec sh -c 'mv "$1" "${1%.html}.htm"' _ {} \;Changes .html extensions to .htm
Search file contents-name "*.cfg" -exec grep -H "error" {} \;Finds lines containing “error” in config files

Use \; when you need one command execution per file, which is safer for operations that modify files. Use + when processing many files with read-only commands like ls or grep to reduce process spawning overhead.

The “Delete old logs” pattern permanently removes files. Always test with -print instead of -exec rm first to verify which files will be affected before running the actual deletion.

Check and Install find on Linux

Most Linux distributions ship with GNU findutils pre-installed, but minimal containers, Alpine-based images, or custom rescue environments might not include it. Verify the version first before relying on advanced options.

Check if find is Installed

Run this command to confirm find is available and check its version:

find --version
find (GNU findutils) 4.9.0
Copyright (C) 2022 Free Software Foundation, Inc.

If you see version output starting with “GNU findutils,” you have the full toolset with all features covered in this guide. If the command is not found, install the package for your distribution.

Install find on Linux Distributions

Ubuntu and Debian-based distributions:

sudo apt install findutils

Fedora, RHEL, Rocky Linux, and AlmaLinux:

sudo dnf install findutils

Arch Linux and Manjaro:

sudo pacman -S findutils

openSUSE:

sudo zypper install findutils

BusyBox find Limitations

On Alpine Linux and other minimal distributions, the default BusyBox find supports basic options including -exec {} \; and -exec {} +, but lacks GNU-specific extensions. The most notable missing feature is -printf, which formats output in custom ways.

If you need -printf for advanced output formatting (used in the rsync example later in this guide), install the full GNU findutils package:

apk add findutils

Practical Examples Using the find -exec Command Option

Backing Up Files with find -exec

When you need to back up specific file types before making changes, find -exec lets you create copies without manually selecting each file. This is useful before running batch updates or testing new scripts that modify originals.

To find and create backups of all .jpg files in the /pictures directory:

find /pictures -type f -name "*.jpg" -exec cp {} {}.backup \;

This command locates each .jpg file and creates a backup by copying each file to a new file with the .backup extension.

Renaming File Extensions Using find -exec

Bulk renaming file extensions is common when migrating projects or standardizing naming conventions across a codebase. The shell’s parameter expansion feature ${1%.html}.htm strips the old extension and adds the new one. For more file moving and renaming techniques, see our mv command guide.

To change the extension of all .html files to .htm in the /web directory:

find /web -type f -name "*.html" -exec sh -c 'mv "$1" "${1%.html}.htm"' _ {} \;

This command renames each .html file, replacing the extension with .htm.

Converting Image Formats with find -exec

When you need to convert image formats in bulk for web optimization or compatibility, find -exec can process entire directories at once. This example requires ImageMagick to be installed (available in most distribution repositories).

To convert all .png images to .jpg in the /images directory:

find /images -type f -name "*.png" -exec sh -c 'convert "$1" "${1%.png}.jpg"' _ {} \;

This wraps convert (part of ImageMagick) in a tiny shell so each .png gains a matching .jpg copy like photo.jpg while leaving the original PNGs untouched.

Compressing Log Files: A find -exec Approach

System logs accumulate rapidly and consume disk space. Compressing older logs preserves history while freeing capacity. The -mtime +7 flag targets files modified more than 7 days ago, ensuring recent logs stay accessible for active troubleshooting.

To find and compress all .log files older than 7 days in /var/log:

find /var/log -type f -name "*.log" -mtime +7 -exec gzip {} \;

This command selects .log files older than 7 days and compresses them using gzip.

Removing Empty Directories with find -exec

Empty directories clutter file systems and complicate backups. The -type d -empty expression isolates directories containing no files or subdirectories. For more directory removal options, see our rmdir command guide.

To find and remove all empty directories in the /data directory, use the -delete action which handles the bottom-up ordering automatically:

find /data -type d -empty -delete

The -delete action is safer than -exec rmdir {} \; because it processes directories in depth-first order, removing children before parents. Without this ordering, you would get errors when find tries to remove a parent directory before its empty subdirectories.

If you prefer the explicit -exec approach, add -depth to force bottom-up processing:

find /data -depth -type d -empty -exec rmdir {} \;

Advanced Use Cases for the find -exec Option

The following examples cover scenarios beyond basic file operations: remote syncing, date stamping, automated reporting, and batch image processing.

Syncing Files to Remote Servers: Advanced find -exec Usage

When you need to back up specific file types to a remote server, combining find with rsync provides efficient incremental transfers. This pattern works well in cron jobs for automated off-site backups.

The following pipeline prints each match relative to /local/docs and hands the entire list to rsync in one invocation, so the directory structure stays intact and files with identical names do not overwrite each other:

find /local/docs -type f -name "*.pdf" -printf '%P\0' | rsync -av --from0 --files-from=- /local/docs/ user@remote_server:/remote/docs/

find uses -printf '%P\0' to emit a null-terminated list of PDFs relative to /local/docs. rsync reads that list with --from0 and --files-from=-, preserves the directory hierarchy under /local/docs, and transfers only the files that changed since the last run.

Date Stamping File Names: A find -exec Technique

Adding timestamps to filenames helps track versions and maintain chronological organization. The $(date +%Y%m%d) command inserts the current date in YYYYMMDD format, while dirname and basename preserve the original directory structure.

To add a current date stamp to the filenames of all .csv files in /data/reports:

find /data/reports -type f -name "*.csv" -exec sh -c 'mv "$1" "$(dirname "$1")/$(date +%Y%m%d)-$(basename "$1")"' _ {} \;

This command locates .csv files and renames each by prefixing the current date, enhancing file organization and version control.

Generating Large File Reports via find -exec

Monitoring disk usage proactively prevents capacity emergencies. This command identifies files consuming significant space and sends a detailed report to administrators, useful for scheduled capacity audits. For more disk analysis techniques, see our du command guide.

To find files larger than 100MB in /home and email a report:

find /home -type f -size +100M -exec ls -lh {} \; | mail -s "Large Files Report" admin@example.com

This command identifies files over 100MB, lists their details, and sends this information via email.

The mail command requires a mail transfer agent (MTA) to be configured. Install mailutils on Debian/Ubuntu or mailx on RHEL-based systems. If email is not configured, redirect output to a file instead: find ... > /tmp/large-files-report.txt

Automated Image Watermarking with find -exec

Protecting image copyrights at scale requires batch watermarking. This example uses ImageMagick’s composite tool to overlay a watermark at 30% opacity in the southeast corner of each image.

To add a watermark to all .jpg images in /images/gallery:

find /images/gallery -type f -name "*.jpg" -exec composite -dissolve 30% -gravity southeast watermark.png {} {} \;

This uses the composite command (part of ImageMagick) to overlay a watermark image on each .jpg file, crucial for copyright protection and branding. Install ImageMagick via your package manager if the composite command is not available.

Directory Creation Based on File Names Using find -exec

Organizing media libraries often requires creating folders matching file names. The basename command extracts the filename without extension, and mkdir -p creates the directory if it does not already exist.

To create directories based on the names of .mp4 files in /videos:

find /videos -type f -name "*.mp4" -exec sh -c 'mkdir -p "/archive/$(basename "$1" .mp4)"' _ {} \;

This pattern passes each matched path to the shell as $1, so basename safely strips the .mp4 extension even when filenames contain spaces, and mkdir -p builds the matching directory under /archive. For more directory management tips, see our mkdir command guide.

Troubleshooting Common find -exec Errors

Missing Argument to -exec

If you see this error:

find: missing argument to `-exec'

The -exec option requires a command terminator. You either forgot the \; or + at the end, or the shell consumed the semicolon before find could see it. Always escape the semicolon with a backslash:

find . -name "*.txt" -exec ls -la {} \;

Single quotes around the semicolon also work: -exec ls -la {} ';'

Permission Denied Errors

When find encounters directories you cannot read, it reports permission errors:

find: '/root': Permission denied
find: '/var/lib/private': Permission denied

To suppress these errors and continue processing accessible files, redirect stderr:

find / -name "*.conf" -exec ls -la {} \; 2>/dev/null

Alternatively, run with sudo if you need to search protected directories.

Files with Spaces or Special Characters

Filenames containing spaces, quotes, or special characters can break commands if not handled properly. When using sh -c, always quote the variable:

# Wrong - breaks on filenames with spaces
find . -name "*.txt" -exec sh -c 'cat $1' _ {} \;

# Correct - quotes protect the filename
find . -name "*.txt" -exec sh -c 'cat "$1"' _ {} \;

The underscore (_) before {} is a placeholder for $0 in the subshell, ensuring the filename becomes $1.

rmdir Fails on Non-Empty Directories

If you see this error when removing directories:

rmdir: failed to remove '/path/dir': Directory not empty

The directory contained files when find checked it or a parent directory was processed before its children. Use -delete or add -depth for proper ordering:

find /data -depth -type d -empty -exec rmdir {} \;

-printf Not Recognized

If you see:

find: unrecognized: -printf

You are using BusyBox find (common on Alpine Linux) which does not support -printf. Install GNU findutils or use an alternative approach:

# Instead of: find . -name "*.pdf" -printf '%P\n'
# Use:
find . -name "*.pdf" -exec basename {} \;

FAQ

When should I use find -exec instead of xargs?

Use find -exec when you need simple, single-file operations or when filenames might contain newlines. Use xargs when you need parallel processing with -P, when processing millions of files where the batching overhead of -exec + is noticeable, or when you need more control over argument placement. For most everyday tasks, find -exec is simpler and safer.

How can I get find to ask for confirmation before each operation?

Use -ok instead of -exec. The -ok option prompts you with y/n for each file before running the command. This is useful when deleting or modifying files where you want to review each match individually. Example: find /data -name "*.tmp" -ok rm {} \; prompts before each deletion.

Conclusion

The find -exec command transforms file searches into automated batch operations, from simple backups to complex multi-step transformations. The key patterns to remember: use {} as the file placeholder, choose \; for single-file execution or + for batched performance, wrap shell expansions in sh -c with properly quoted variables, and always preview destructive operations with -print before committing to -exec rm or -delete.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffee Buy me a coffee

Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags:

You type Result
<code>command</code> command
<pre>block of code</pre> code block
<strong>bold</strong> bold
<em>italic</em> italic
<a href="URL">link</a> link
<blockquote>quote</blockquote> quote block

Leave a Comment

We read and reply to every comment — let us know how we can help or improve this guide.

Let us know you are human: