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.

Author: dt

Created: 2022-02-20 Sun 10:16