What is xargs in Linux

Bits Lovers
Written by Bits Lovers on
What is xargs in Linux

What is xargs in Linux: 20 practical examples

The xargs command builds command lines from standard input. It’s one of those tools that seems simple until you need it, then it becomes indispensable. I use xargs daily for batch operations, and once you understand these patterns, you will too.

Let me walk through the examples I actually use.

Handling “Argument list too long” errors

You’ve probably seen this when trying to delete lots of files:

rm *.log
bash: /bin/rm: Argument list too long

xargs bypasses the argument limit by processing inputs in batches:

find ~ -name '*.log' -print0 | xargs -0 rm -f

The -print0/-0 combo handles filenames with spaces or special characters. I’ll explain why that matters later.

Formatting output

Turn multi-line output into a single line:

ls -1 Images/bitslovers/ | xargs

This is handy when you need to pass a file list as arguments to another command.

Counting lines in multiple files

ls *upload* | xargs wc

This runs wc on each file, giving you line/word/character counts for the whole batch.

Finding and removing files

Recursively remove specific files (this removes the file, not directories):

find . -name "bitslovers_backup" -type f -print0 | xargs -0 /bin/rm -v

Note: I removed the -rf flags from the original example. Using -rf with xargs is overkill and dangerous—let xargs handle the recursion through find.

Handling spaces in filenames

The original post had this wrong. Let me fix it.

If you have a file named “file 1.log”, this fails:

find ./log -type f | xargs rm
# rm: cannot remove './log/file': No such file or directory
# rm: cannot remove '1.log': No such file or directory

xargs splits on spaces by default, so “file 1.log” becomes two arguments. Fix it with -I:

find ./log -type f | xargs -I % rm "%"

Or better yet, use -print0/-0 (I’ll show you why):

find ./log -type f -print0 | xargs -0 rm

Dealing with quotes in filenames

Filenames with quotes break xargs in weird ways:

find ./log -type f | xargs rm
# xargs: unmatched double quote; by default, quotes are special to xargs unless you use the -0 option

Quoting the placeholder doesn’t help—xargs still chokes on the quotes.

The fix: Use null separators instead of newlines:

find ./log -type f -print0 | xargs -0 rm

-print0 terminates filenames with null bytes. -0 tells xargs to expect null-terminated input. This handles spaces, quotes, newlines—anything.

Some commands can’t accept null input (head, tail, ls, wc, sed). For those, you’re stuck with the -I placeholder approach.

Creating archives from found files

find Images/bitslovers/ -name "*.jpg" -type f -print0 | xargs -0 tar -cvzf image.tar.gz

Copying a file to multiple directories

echo ./Blog/ ./Documents/ | xargs -n 1 cp -v ./Downloads/bitslovers-best-way-to-use-xargs.xlsx

-n 1 runs cp once per directory.

Renaming files to lowercase

The original example had syntax issues. Here’s a working version:

find Documents -depth -name '*[A-Z]*' | while read file; do mv "$file" "$(dirname "$file")/$(basename "$file" | tr 'A-Z' 'a-z')"; done

Actually, that’s messy. Let me use a more practical approach with the rename command:

find Documents -depth -name '*[A-Z]*' -exec rename 'y/A-Z/a-z/' {} +

(Assuming you have the Perl-based rename utility installed.)

Reading input from a file

xargs -a bitslovers_links.txt wget -c

Use -a to read from a file instead of stdin. Great for batch downloads.

Verbose mode

See what xargs is about to run:

find . -name "*.conf" | xargs -t ls -l

-t prints each command to stderr before executing it. Useful for debugging.

Interactive mode

Prompt before running each command:

echo ./Blog/ ./Documents/ | xargs -p -n 1 cp -v ./Downloads/file.xlsx

Type y to execute, n to skip. Combine with -t to see the full command first.

Parallel execution

This is xargs superpower. Run commands in parallel:

find . -name "*.jpg" | xargs -P 4 convert -resize 50% {}

-P 4 runs up to 4 processes simultaneously. Perfect for CPU-intensive operations on multi-core systems.

You can even adjust parallelism on the fly with signals (SIGUSR1 increases, SIGUSR2 decreases). Though honestly, I rarely use that—I just pick a good -P value upfront.

Inserting arguments anywhere

By default, xargs appends arguments to the end of the command. Use -I to place them anywhere:

find ./log -type f -name "*.log" | xargs -I % mv % tmp/

You can use any placeholder string—I like % but {} is common too.

Listing all users

cut -d: -f1 < /etc/passwd | sort | xargs

Turns a column of usernames into a space-separated list.

Using custom delimiters

printf "file1.txt\nfile2.txt\nfile3.txt" | xargs -d '\n' -I {} cp {} /backup/

-d lets you specify any delimiter. Though honestly, -0 is safer for most use cases.

Kubernetes: Delete pods by pattern

kubectl get pods -n namespace | awk '{print $1}' | grep "pods-name*" | xargs kubectl delete pod

List pods → extract names → filter → delete. Classic pipeline.

Things I’ve learned the hard way

1. Always use -print0/-0 for file operations

Newlines are valid characters in Unix filenames. Spaces are common. Null bytes are the only safe delimiter.

2. The -i flag is deprecated

Use -I instead. Same functionality, POSIX standard.

3. xargs doesn’t know about exit codes

If a command fails, xargs keeps going. Check exit codes explicitly if you need to stop on errors:

find . -type f | xargs -I {} sh -c 'command "{}" || exit 255'

4. Some commands can’t handle null separators

Commands like head, tail, ls, wc, and sed don’t support -0. For those, you’re stuck with newlines and -I.

5. Parallel xargs processes share stdout

If you use -P, output from different processes gets mixed together. Redirect to files or use --process-slot-var to separate output.

New in recent versions

Since the original post (2021), a few things changed:

  • POSIX standardization: -print0 and -0 will be standardized in POSIX Issue 8
  • Better signal handling: xargs -P no longer changes SIGUSR1/SIGUSR2 handling unless you actually use -P
  • Improved child process handling: xargs -P now waits for all children to complete, even if one exits with status 255
  • Deprecated options: -l and -i are deprecated—use -L and -I instead

Check man xargs for the full story on your system.

When to use xargs (and when not to)

Good for xargs:

  • Simple command execution on found files
  • Parallel processing with -P
  • Building command lines from lists
  • Bypassing argument length limits

Better alternatives:

  • find -exec ... + for simple operations (fewer processes)
  • find -execdir ... {} + for security (runs in file’s directory)
  • Shell loops for complex logic
  • GNU parallel for advanced parallelization

Conclusion

xargs has been around since the 1980s, and it’s still relevant because it solves a fundamental problem: how do you turn data into commands?

The examples I showed are starting points. Once you understand the patterns—-print0/-0 for files, -I for argument placement, -P for parallelism—you’ll find yourself reaching for xargs constantly.

Just remember: use null separators for filenames, test with -t before running destructive commands, and check man xargs when you need something beyond the basics.

The xargs manual page has more examples than I could fit here. Go explore.

Bits Lovers

Bits Lovers

Professional writer and blogger. Focus on Cloud Computing.

Comments

comments powered by Disqus