xargs
turn a list into argumentsxargs bridges two kinds of command: ones that print a list, and ones that want their input as arguments, not on a pipe — rm, cp, chmod. It reads the list and builds the command line.
find produces names; xargs hands them to the command that acts on them.
At the terminal
Read the session first, then the notes: each numbered line in the output is answered by the note with the same number.
What the numbered lines are telling you
find printed the names, and xargs ran a single "rm -v ./cache/a.tmp ./cache/b.tmp".
Three separate echo commands, each given one word.
-print0 and -0 separate names with a null byte instead of a new line, so names with spaces are passed correctly.
Each line of hosts.txt is put where {} appears, and ping runs once per host.
Switches
A switch changes how the command behaves. These are the ones used day to day; man xargs lists the rest. Single-letter switches can usually be joined, so -l -a may be written -la.
-n NUM- Use at most NUM arguments per command.
-I {}- Replace {} in the command with each input item.
-0- Expect items separated by null bytes, as from find -print0.
-P NUM- Run up to NUM commands in parallel.
-p- Prompt: show each command and ask before running it.
-r- Do not run the command at all if there is no input.
Variations worth knowing
The same tool, pointed at a narrower question. These four cover most of what it is reached for day to day.
grep -rl "old-domain" . | xargs sed -i "s/old-domain/new-domain/g"Replaces text in every file that contains it.
cat urls.txt | xargs -n 1 -P 4 curl -sODownloads four at a time, in parallel.
find . -type f | xargs -p rmShows the command and asks before running it.
ls *.jpg | xargs -I {} mv {} photos/Moves each file into a directory.
In cybersecurity
xargs runs commands built from data it was handed, so the data matters.
Without -0, a file called "my notes.txt" becomes two arguments, and rm may delete a different file called "my". Use -print0 with -0.
A file named "-rf" is read as a switch by the command. Put -- before the arguments so nothing after it is treated as an option.
Replace rm with echo, or use -p, to see the command that would run before letting it loose.