Find files and act on them
Search directory trees by name, type, size and age with find, and feed the results to other commands.
- Search directory trees with find’s tests: -name, -type, -size, -mtime
- Act on results with -exec and xargs
- Handle file names with spaces safely using -print0 and xargs -0
Globs only look in one directory. find walks a whole tree and tests every file it meets:
1find . -name "*.log" # by name (quote the pattern!)
2find . -iname "readme*" # case-insensitive name
3find /var/log -type f -size +10M # regular files bigger than 10 MB
4find . -type d -name cache # directories called cache
5find . -mtime -1 # modified in the last 24 hours
6find . -maxdepth 1 -empty # empty things, without descending
7find . -name "*.tmp" -o -name "*.bak" # -o means OR
8find . ! -name "*.sh" # ! means NOTQuote the pattern: unquoted, the shell would expand *.log against the current directory before find even starts.
1cd "$(mktemp -d)"
2mkdir -p station/{deck1,deck2/lab,archive}
3touch station/deck1/engine.log station/deck2/lab/samples.csv
4touch station/deck2/lab/scope.log station/archive/old.log station/readme.txt
5find station -name "*.log" | sort
6echo "--"
7find station -type d | sort
8echo "--"
9find station -name "*.log" -not -path "*/archive/*" | sortstation/archive/old.log station/deck1/engine.log station/deck2/lab/scope.log -- station station/archive station/deck1 station/deck2 station/deck2/lab -- station/deck1/engine.log station/deck2/lab/scope.log
find lists files in whatever order the filesystem stores them, so pipe to sort when you need a stable order.
Doing something with what you found
Three ways to act on each result:
-exec cmd {} \;runscmdonce per file, with{}replaced by the path. The\;(escaped so the shell doesn’t eat it) ends the command.-exec cmd {} +packs as many paths as fit into each run ofcmd- much faster for many files.-deleteremoves what matched. Run the samefindwithout it first!
xargs is the general version: it reads words from stdin and turns them into arguments for a command. find . -name "*.log" | xargs wc -l counts the lines of every log.
1cd "$(mktemp -d)"
2mkdir notes
3printf 'a\nb\n' > "notes/mission log.txt"
4printf 'c\n' > notes/todo.txt
5find notes -name "*.txt" | sort | xargs cat 2>&1 | head -n 2
6echo "--"
7find notes -name "*.txt" -print0 | xargs -0 cat | wc -l
8find notes -name "*.txt" -exec wc -l {} + | sortcat: notes/mission: No such file or directory cat: log.txt: No such file or directory -- 3 1 notes/todo.txt 2 notes/mission log.txt 3 total
Key takeaways
findwalks a tree, testing-name,-type,-size,-mtimeand more.Quote name patterns so the shell doesn’t expand them.
-exec ... {} +andxargsrun commands on the results.Use
-print0 | xargs -0whenever file names might contain spaces.
Lesson quiz
7 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: write Bash scripts
Write a script in the editor and run it for real against sample input. Each run gets a fresh Linux sandbox with Bash 5.2 and the GNU tools on Wandbox, a free public service - so experiment freely, even with rm. Your script and test input are sent there.
Round up the logs
The starter builds a small station tree. Print the path of every .log file under station, skipping anything in archive, sorted. Then print how many there were.
Expected output:
1station/deck1/engine.log
2station/deck2/lab/scope.log
3station/deck3/reactor.log
43- Finds three logs
Your script runs with Bash 5.2 and GNU tools on Wandbox, a free public service, in a fresh sandbox each time. Your script and test input are sent to that service.
Count every line
The starter writes some notes, one with a space in its name. Print the total number of lines across all .txt files under notes - just the number. Make it safe for spaces in names.
- Counts six lines
Your script runs with Bash 5.2 and GNU tools on Wandbox, a free public service, in a fresh sandbox each time. Your script and test input are sent to that service.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…