Xargs
Table of Contents
What is xargs?
Execute a command with piped arguments coming from another command, a file, etc. The input is treated as a single block of text and split into separate pieces on spaces, tabs, newlines and end-of-file.
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.
Examples
Run a command using the input data as arguments:
arguments_source | xargs command
Run multiple chained commands on the input data:
arguments_source | xargs sh -c "command1 && command2 | command3"
Take output from cat and create an argument list
cat list | xargs
Wait! I thought xargs took output from command and passed it into another command. So what command is xargs using here?
The -t flag
cat list | xargs -t
You will see that xargs uses echo since we didn’t specify another command.
The -n flag
cat list | xargs -t -n 1
It echos them one at a time now instead of a single echo.
Generate a compact list of all Linux user accounts on the system
cut -d: -f1 < /etc/passwd | sort | xargs
ls example
/bin/ls /bin/ls | xargs ls
the -I flag
The braces symbolize all the input
ls | xargs -I {} echo "/home/dt/{}"
The X’s symbolize all the input
ls | xargs -I XXXX echo "/home/dt/XXXX"
Make 1000 sequential .txt files
seq 1000 | xargs -I {} touch {}.txt
convoluted example
/bin/ls | cut -d. -f1 | grep -v list | xargs -I {} mv {}.txt {}.text
Mkdir
echo 'one two three' | xargs mkdir ls one two three
When filenames contains spaces you need to use -d option to change delimiter touch ’test file’
/bin/ls | xargs -n 1
test and file are on their own lines…not good!
/bin/ls | xargs -n 1 -d \n
Sets new lines as delimiter and now output is good.
Find
Delete all files with a `.backup` extension (`-print0` uses a null character to split file names, and `-0` uses it as delimiter):
find . -name '*.backup' -print0 | xargs -0 rm -v
Rm files older than two weeks in the /tmp folder
find /tmp -mtime +14 | xargs rm
xargs vs exec The find command supports the -exec option that allows arbitrary commands to be performed on found files. The following are equivalent.
find foo -type f -name "*.txt" -exec rm {} \; find foo -type f -name "*.txt" | xargs rm
So which one is faster? Let’s compare a folder with 1000 files in it.
time find . -type f -name "*.txt" -exec rm {} \; 0.35s user 0.11s system 99% cpu 0.467 total time find . -type f -name "*.txt" | xargs rm 0.00s user 0.01s system 75% cpu 0.016 total
Clearly using xargs is far more efficient. In fact several benchmarks suggest using xargs over exec {} is six times more efficient.
Parallel runs of up to `max-procs` processes at a time; the default is 1. If `max-procs` is 0, xargs will run as many processes as possible at a time:
arguments_source | xargs -P max-procs command seq 5 | xargs -n 1 -P 1 bash -c 'echo $0; sleep 1'
Footer
Copyright © 2020-2021 Derek Taylor (DistroTube)
This page is licensed under a Creative Commons Attribution-NoDerivatives 4.0 International License (CC-BY-ND 4.0).
The source code for distro.tube can be found on GitLab. User-submitted contributions to the site are welcome, as long as the contributor agrees to license their submission with the CC-BY-ND 4.0 license.