xargs
Table of Content
General
xargs is parto fo the findutils (at least in debian), so if you run a debian minimal and want to have it available on your system, you have to install the package findutils
The xargs
command in UNIX is a command line utility for building an execution pipeline from standard input. Whilst tools like grep
can accept standard input as a parameter, many other tools cannot. Using xargs
allows tools like echo
and rm
and mkdir
to accept standard input as arguments.
How to use xargs
By default xargs
reads items from standard input as separated by blanks and executes a command once for each argument. In the following example standard input is piped to xargs and the mkdir
command is run for each argument, creating three folders.
$ echo "one two three" | xargs mkdir
$ ls
one two three
When filenames contains spaces you need to use -d
option to change delimiter
How to use xargs with find
find /tmp -mtime +14 | xargs rm
xargs VS exec
Compare run (on a vm) removing 10k files located in current directory without any sub dirs
Using finds exec
$ time find ./ -type f -exec rm {} \;
9.48s user 5.56s system 97% cpu 15.415 total
Using xargs
$ time find ./ -type f | xargs rm
find ./ -type f 0.01s user 0.01s system 88% cpu 0.029 total
xargs rm 0.03s user 0.44s system 93% cpu 0.500 tota
How to print commands that are executed
For debugging purpose, you can add the parameter -t
to printout the commands which gets executed
$ find ./ -type d | xargs -t -I % sh -c 'echo %'
sh -c 'echo ./'
./
sh -c 'echo ./one'
./one
sh -c 'echo ./two'
./two
sh -c 'echo ./three'
./three
How to run multible commands with xargs
It is possible to run multiple commands with xargs
by using the parameter -I
.
This replaces occurrences of the argument with the argument passed to xargs.
$ find ./ -type d | xargs -t -I % sh -c 'echo %; touch %/file.txt'
sh -c 'echo ./; touch .//file.txt'
./
sh -c 'echo ./one; touch ./one/file.txt'
./one
sh -c 'echo ./two; touch ./two/file.txt'
./two
sh -c 'echo ./three; touch ./three/file.txt'
./three
$ ls *
file.txt one two three
one:
file.txt
two:
file.txt
three:
file.txt