Shell, explained
find . -name "*.log" | xargs rm, explained
find . -name "*.log" | xargs rm
find lists every .log file below the current folder, one path per line. xargs reads those lines and runs rm with all of them as its arguments, so every file found is deleted. The quotes around *.log matter: they let find, not the shell, do the matching.
Lines become arguments
xargs collects the three paths and runs one rm with all of them. rm prints nothing when it succeeds.
Tap a part of the command to find it below
3 lines become arguments for rm
Without the quotes, the shell gets there first
app.log is in the current folder, so the shell turns *.log into app.log before find starts. find then only finds files named exactly app.log.
Tap a word to follow it
find never sees the pattern: ./old/cron.log and ./old/debug.log are missed.
find receives 3 arguments
Part by part
find .- Searches the current folder and everything below it.
-name "*.log"- Matches names ending in .log. The quotes pass the * to find instead of letting the shell expand it.
|- Sends the list of paths, one per line, into xargs.
xargs- Reads lines from its input and runs a command with them as arguments.
rm- The command xargs runs: it deletes the files it is given.
Common mistakes
File names with spaces
xargs splits on spaces, so ./my app.log becomes ./my and app.log. Use find . -name "*.log" -print0 | xargs -0 rm, which separates names with a null character instead.
Deleting before looking
Run the same command with echo first (… | xargs echo rm) to see exactly what would be deleted.
Try it
$ find . -name "*.log"Preview the list first.
$ find . -name "*.log" -print0 | xargs -0 rmSafe with spaces in names.
$ find . -name "*.log" -deleteLet find delete them itself.
Questions
Why not rm $(find . -name "*.log")?
It has the same problem with spaces, and with thousands of files it can exceed the maximum command length. xargs splits a long list into several rm runs for you.
Is find -delete better?
For plain deletion, yes: there is no pipe, and spaces and odd characters are no problem. xargs is the general tool for running any command on a list.
What does the . after find mean?
It is the folder to search: . means the current one. find /var/log -name "*.log" searches somewhere else.
Terminaster
Ask about any command and get a picture like this one.
The Terminaster tutor draws these visuals for your own questions, then turns what you learned into spaced-repetition cards so it sticks.
The ideas behind it
Building arguments with xargs
xargs reads input records and constructs one or more command invocations whose argument lists contain those records, subject to parsing and size options.
Null-delimited filenames
A null-delimited pathname stream terminates each pathname with a zero byte, the one byte that cannot occur inside a Unix pathname component.
Filename expansion (globbing)
Filename expansion is the shell step that replaces unquoted pathname patterns such as *, ?, and bracket expressions with matching existing pathnames before launching a command.