As a Linux power user, you likely have thousands of files scattered across various directories and mounts. Manually searching through this haystack to find the needles you need would be an exercise in futility. Thankfully, Linux offers two indispensable file-finding utilities: locate and find.

Of these two, find is the more versatile option. With find, you can craft targeted searches using a wide range of criteria like filenames, size, permissions, modification time, and more. This level of fine-tuned control makes find an administrator‘s best friend.

But find’s real power lies in its ability to couple searches with actions using the -exec argument. By tackling find and -exec, you can eliminate tedious manual file operations. Intrigued? Read on to master this dynamic Linux command.

Understanding Find Basics

Before diving into -exec, let’s build find command familiarity. Here is the basic syntax:

find [search location] [criteria]

For example, to hunt for a file named secret.txt on the entire system, you would run:

find / -name secret.txt

As you can see, you first specify the top-level directory under which find starts the search using / for the system root. Next, criteria like -name narrow results by attributes like the filename.

Without any criteria defined, find descends into the search location and prints full paths for every file, directory, and special file. This full filesystem traversal makes find slower than locate in some cases. However, find searches live data rather than relying on an indexed database.

You can specify an extensive array of criteria options:

  • -name – Search by complete or partial filename
  • -size – Filter by file size thresholds
  • -mtime – Search by file modification times
  • -perm – Match based on file permissions
  • -user – Find files belonging to specific owners
  • -group – Locate files assigned to particular groups
  • -type – Select block device files, character device files, symlinks, etc.
  • -inum – Match based on inode number
  • -links – Filter by link counts pointing to a file
  • -logical operators – Combine criteria with AND/OR/NOT
  • -depth / -noleaf – Descend fully into subdirectories orconstrain checks to paths

Mix and match to hone in on precisely the results you want. With over 85 possible criteria, find offers incredible search refinement capabilities.

Now let’s look at turning those results into actions.

Acting on Find Results with -exec

While basic searches serve a purpose, find becomes far more useful when chaining commands that operate on matching files. The -exec argument facilitates this by feeding found files as arguments to Linux utilities and scripts.

Here is the syntax:

find [starting directory] [search criteria] -exec [command] [options] [replacement token] [delimiter]

Let’s break this template down piece by piece:

  • [starting directory] – Top-level location where find starts the search
  • [search criteria] – Conditions like -name that filter results
  • -exec – Flag enabling execution of commands against results
  • [command] – The program or script invoked for each result
  • [replacement token] – Placeholder replaced by the path of each match
  • [delimiter] – Punctuation determining command execution cadence

The command kicks off when find locates the first match. It substitutes the full pathname for the replacement token, executes the command, and awaits the delimiter. This sequence repeats for each subsequent result.

Replacement Token Placeholders

In the syntax template, you may have noticed an ambiguous [replacement token]. By convention, this placeholder is typically {} but find permits other alphanumeric options.

When find passes a match to -exec, the token swaps out with the actual pathname. Contrast running find alone versus harnessing -exec:

find /home -name notes.txt

/home/john/notes.txt
/home/jane/notes.txt  

Versus:

find /home -name notes.txt -exec cat {} \;  

[Contents of /home/john/notes.txt display]
[Contents of /home/jane/notes.txt display]

Thanks to {}, the cat utility received each textual file as an argument in place of the bracketed letters.

Delimiters Impact Command Execution Cadence

The syntax also includes a delimiter like ; or +. This punctuation determines whether find invokes the command uniformly or collectively across results.

Using a ; delimiter translates to:

Run command against match #1;
Run command against match #2;
Run command against match #3;

With a + delimiter find passes all results simultaneously:

Run command against match #1 match #2 match #3

Let’s see delimiters in action to cement the contrast:

; Delimiter – Per-File Execution

find /home -name notes.txt -exec cat {} \; 

Produces:

[Contents of /home/john/notes.txt display] 
[Contents of /home/jane/notes.txt display]

+ Delimiter – Group Execution

find /home -name notes.txt -exec cat {} +  

Produces:

[Contents of /home/john/notes.txt display] 
[Contents of /home/jane/notes.txt display] 

The output ordering might differ slightly but the key takeaway is that + chained the files together as arguments versus invoking cat separately per result.

Now that you understand the basics of replacement tokens and delimiters, let’s walk through some practical examples.

Simple Use Case: File Content Display

A common task is checking configuration file contents across multiple subdirectories. Without find, you would need to remember every location and perform repetitive commands. Let find and -exec tackle the heavy lifting instead.

Consider a project directory /code with config.txt copies in the python, node, and java subfolders. You need to assess the settings defined across each one.

Rather than manually catting three separate paths, run:

find /code -name config.txt -exec cat {} + 

This:

  1. Searches /code for filename matches to config.txt
  2. Passes all results as arguments into a single cat invocation
  3. Prints the content for python/config.txt, node/config.txt, and java/config.txt

You eliminate redundant commands and view all relevant files with one operation.

Batch File Renames

Finding specific files for renaming across distributed directories is another ideal use case. Picture an organization that stored scanned payment receipts on a central file server in domains per department.

Unfortunately, employees never followed a coherent file naming standard. You now need to mass rename everything for compatibility with new OCR automation software.

Rather than tracking down each department share and using cumbersome wildcards, harness find and -exec for heavy lifting:

find /scans -type f -exec mv {} processed-{} \; 

Breaking this down:

  • Searches all directories below /scans
  • Filters to only files with -type f
  • Mass renames all matches by prepending "processed-" using mv
  • \; delimiter invokes mv separately for each found file

The software now sees uniformly named processed-receipt001.pdf, processed-receipt002.pdf, etc. Despite inconsistencies in original placement, you simplified a complex renaming task.

Scalable File Archive Management

As storage efficiency grows in importance, moving files into properly organized archives jumps as a priority. Utilization rates on enterprise filesystems now exceed 80% on average. Capacity planning teams forecast 30-50% annual data growth.

This explosion makes manually sorting accumulating files untenable. Combining find and -exec instead provides a scalable archival management solution.

For example, to locate assorted project deliverables scattered among engineers’ home directories for archiving, utilize this command structure:

find /home -type f -name project\* -exec cp {} /archives/projects/{} +

The breakdown:

  • Searches starting at /home encompassing all user directories
  • Filters to only files (-type f)
  • Matches project* filenames using wildcard
  • Copies (cp) results to /archives/projects path
    • concatenates multiple matches as cp arguments
  • {} substitutes each filename into target path

This skeleton suits general deployment too. Modify the start path, search criteria, destination directory, and utilities like mv as needed.

Automate archive clean-up by coupling deletion instead of copying:

find /archives/projects -mtime +180 -exec rm {} \;

Here files untouched for 180 days purge from the projects repository. Set your target retention age as desired.

Eliminating Wasted Storage Capacity

Managing storage growth presents a huge challenge. IDC estimates that 60%+ of enterprise data duplicates across siloed repositories. Complicating management, deletes merely unlink rather than erasing.

Orphaned cache directories, expired build artifacts, stale application codes, and dead projects leave terabytes of wasted space. Unfortunately, piecing these together manually proves impossible.

Brace find and -exec to systematically wipe this forgotten space:

find /opt -type d -name node_modules -exec rm -rf {} +   
find /var/tmp -mtime +30 -exec rm -rf {} \; 

Scenario #1 eliminates development dependency directories typically replicated on all engineers’ systems. Scenario #2 removes temporary directories more than 30 days old.

Adjust your criteria, target locations, and age threshold as appropriate. But staggered deletion prevents storage system disruption. Regular runs reclaim GBs to PBs over time depending on environment scale.

Configuration File Comparisons

Another common challenge is identifying discrepancies among configuration files, application versions, DLLs/shared objects, or other matching artifacts. IT teams often expend copious hours manually contrasting directories.

Find and -exec present a simpler solution – hash generation plus comparison. Hashing using utilities like md5sum or sha256sum boil files down to encoded signatures representing contents. Matching hashes indicate identical data.

Here is an example flowed:

find /opt -name app.config -exec md5sum {} + > live_hashes.txt  
find /backups -name app.config -exec md5sum {} + > backup_hashes.txt

diff live_hashes.txt backup_hashes.txt

This:

  • Finds all app.config files under /opt and /backups
  • Generates independent md5sums for each set
  • Outputs signatures into separate files
  • Compares the hash results using diff

With this approach, you obtain differs signaling config de-synchronizations. The same method applies for security policy checks, registry integrity validation in Windows, etc.

Automate these scans to detect and address configuration drifts before system outages or failed builds occur. Schedule runs aligning to your release cycles, infrastructure change rates, compliance requirements, etc.

Scheduling Recurring Operations

While embracing find’s capabilities interactively delivers value, scripting recurring execution magnifies usefulness even further. Scheduled sweeps address multiple admin needs:

  • Rotate verbose server logs to control disk usage
  • Generate hourly configuration and registry snapshots
  • Sync designated source and replica directories
  • Collect asset inventories across enterprise systems

Cron provides a native task scheduler on Linux systems. Using a crontab entry, administrators can trigger find commands at recurring intervals.

Some examples include:

# Rotate verbose Glassfish logs nightly  
0 2 * * * find /var/log/glassfish -type f -exec cp {} /archives/glassfish/{} \;   

# Generate and archive incremental file hashes hourly   
0 * * * * find /home -type f -exec md5sum {} + > /checksums/homedirs-$(date +%Y%m%d%H%M).txt

# Mirror designated source directories every 30 minutes   
*/30 * * * * find /important/prod_data -exec rsync -av {} /protected/{} + 

Set frequencies aligning to your RTO/RPO standards for backups as well as business needs. Wrapping commands in scripts adds further possibilities for customization as well.

Integrating Other Core Utilities via Xargs

So far the examples leverage -exec for acting on find results. However, Linux offers a similar utility called xargs capable of chaining command execution too.

Xargs takes input from standard input (stdin) rather than specifying a command directly. This allows piping find results into xargs to construct execution pipelines.

For example:

find /var/log -name *.log -print0 | xargs -0 rm {}

Here print0 passes NUL delimited results from find to xargs. The -0 flag then translates the terminated records properly.

Contrast the flow without xargs:

find /var/log -name *.log -exec rm {} \;

Xargs introduces additional flexibility in terms of command grouping, parallelization, continuation across multiple runs, and handling special characters.

Explore more tips on xargs, -exec, and alternative find result consumers like awk, sed, and grep to multiply possibilities.

Secure Deletion and Audit Controls

When managing confidential data, deleting files securely jumps in importance. Storage media retains traces of previous writes. So findings and erasing sensitive materials requires safeguards against forensic recovery.

Tools like shred complement find for enhanced deletion use cases:

find /allssd -name *.pdf -exec shred -fuz {} \;

Here shred overwrites all found PDFs three times (f) with random data (z) before unlinking the path (u). This frustrates recovery attempts from residual artifacts.

Auditing also grows in relevance when operating on critical data. Ensure find actions write to syslog or designated audit logs by default. And utilize features like atime/ctime tracking to construct chains of custody around modifications.

Consider find‘s impact relating to compliance mandates as well. Features like size filters could violate data preservation safe harbor rules. Seek legal guidance tailoring robust yet compliant search/delete policies.

Unleash Your Linux Administrator Arsenal

Find’s immense flexibility coupled with interoperability across other CLI tools via -exec open automation possibilities. Fade frustration pinpointing important files scattered across disparate filesystem paths.

Let find retrieve matches so you can analyze configurations, enact edits, mirror, migrate, synchronize, archive, securely delete, or take bulk actions against results. Then harness other Linux mainstays like awk, sed, grep, and xargs to further process outputs.

Know other handy find and -exec tricks? Share your favorites! Harnessing Linux’s strengths accelerates all our progress and productivity. Keep pushing the boundaries of what’s possible!

Similar Posts