xargs Command Builder

xargs cheatsheet — build and execute commands from stdin. find . -name '*.log' | xargs rm, xargs -I{} cp {} backup/, xargs -P4 parallel execution. Essential Linux pipe tool.

6 min read

What it is

xargs builds and executes command lines from standard input, allowing you to process lists of items with arbitrary commands.

Installation

Linux:

sudo apt update && sudo apt install findutils  # Debian/Ubuntu
sudo yum install findutils                   # CentOS/RHEL
sudo dnf install findutils                   # Fedora

macOS: xargs is typically pre-installed with macOS. If not:

brew install findutils

(You might need to alias xargs to gxargs if you installed from findutils via Homebrew to avoid conflicts with the built-in xargs).

Windows: xargs is not a native Windows command. You can achieve similar functionality using PowerShell loops or by installing a Linux environment like WSL (Windows Subsystem for Linux).

Core Concepts

xargs reads items from standard input, delimited by blanks (by default) or newlines, and executes a specified command using these items as arguments. It’s particularly useful for processing the output of other commands like find, grep, or ls.

Commands / Usage

Basic Execution

  • Run a command with arguments from stdin:

    echo "file1.txt file2.txt" | xargs touch
    

    Creates two empty files named file1.txt and file2.txt.

  • Run a command with arguments from stdin, one per line:

    printf "line1\nline2\nline3\n" | xargs -L 1 echo
    

    Outputs:

    line1
    line2
    line3
    
  • Run a command once with all arguments from stdin:

    echo "arg1 arg2 arg3" | xargs echo
    

    Outputs: arg1 arg2 arg3

Controlling Argument Placement

  • Specify where arguments are inserted using -I (or -i):

    echo "file1.txt file2.txt" | xargs -I {} mv {} {}.bak
    

    Renames file1.txt to file1.txt.bak and file2.txt to file2.txt.bak. The {} is a placeholder for the input item.

  • Use a different placeholder with -I:

    find . -name "*.log" | xargs -I FILENAME cp FILENAME /backup/
    

    Copies all .log files found in the current directory and its subdirectories to /backup/, using FILENAME as the placeholder.

Controlling Execution Behavior

  • Execute the command only once, regardless of the number of arguments:

    ls *.txt | xargs echo "Found:"
    

    Outputs: Found: file1.txt file2.txt ... (all .txt files on one line after "Found:")

  • Execute the command multiple times, with a limited number of arguments per execution (-n):

    seq 1 10 | xargs -n 3 echo
    

    Outputs:

    1 2 3
    4 5 6
    7 8 9
    10
    
  • Execute the command with a maximum number of arguments per line (-L):

    printf "a\nb\nc\nd\ne" | xargs -L 2 echo
    

    Outputs:

    a b
    c d
    e
    

    (Note: -L splits input by lines, -n splits input by items and limits how many items go into one command execution).

  • Prompt before each command execution (-p):

    echo "file1.txt file2.txt" | xargs -p rm
    

    Will prompt: rm file1.txt file2.txt ? (y/n).

  • Execute commands in parallel (-P):

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

    Resizes all .jpg files in parallel using 4 worker processes, creating small_ prefixed versions.

  • Specify the maximum number of parallel processes (-P):

    seq 1 100 | xargs -P 8 -n 1 sleep 1
    

    Runs 100 sleep 1 commands, with up to 8 running concurrently.

Handling Special Characters and Whitespace

  • Treat input as null-delimited items (-0): Essential when dealing with filenames containing spaces, newlines, or other special characters. Often used with find -print0.

    find . -name "* *" -print0 | xargs -0 rm
    

    Safely removes files with spaces in their names.

  • Change the delimiter (-d):

    echo "item1:item2:item3" | xargs -d : echo
    

    Outputs: item1 item2 item3

  • Use specific delimiters for -I:

    echo "user1,user2,user3" | xargs -d ',' -I {} echo "Processing user: {}"
    

    Outputs:

    Processing user: user1
    Processing user: user2
    Processing user: user3
    

Other Useful Flags

  • Do not execute, just print the command line (-t):

    echo "file1.txt file2.txt" | xargs -t touch
    

    Prints: touch file1.txt file2.txt and then executes it.

  • Specify the command to run (-a): Reads arguments from a file instead of stdin.

    # Create a file with arguments
    echo "fileA.txt" > my_files.txt
    echo "fileB.txt" >> my_files.txt
    
    # Use xargs with the file
    xargs -a my_files.txt touch
    

    Creates fileA.txt and fileB.txt.

  • Set the maximum argument list length (-s): (Rarely needed, defaults are usually fine).

    # Example: Limit command line length to 100 characters
    seq 1 1000 | xargs -s 100 echo
    
  • Specify the initial arguments for the command (--arg-file):

    # Create a file with initial arguments
    echo "-l" > options.txt
    echo "-a" >> options.txt
    
    # Use xargs with initial arguments from a file
    echo "file1.txt file2.txt" | xargs --arg-file=options.txt ls
    

    Equivalent to ls -l -a file1.txt file2.txt.

  • Specify the maximum number of arguments (-n): (Already covered above, but important).

    echo "a b c d e" | xargs -n 2 echo
    

    Outputs:

    a b
    c d
    e
    
  • Specify the delimiter (-d): (Already covered above, but important).

    echo "one,two,three" | xargs -d ',' echo
    

    Outputs: one two three

Common Patterns

  • Find and delete files with spaces in their names:

    find . -type f -name "* *" -print0 | xargs -0 rm
    
  • Find and move files to a directory:

    find . -name "*.tmp" -print0 | xargs -0 -I {} mv {} /path/to/archive/
    
  • Count lines in multiple files found by grep:

    grep -l "pattern" *.log | xargs -I {} wc -l {}
    
  • Process files in parallel using find and xargs:

    find . -name "*.png" -print0 | xargs -0 -P 8 -I {} convert {} -quality 85 {}
    

    (Converts PNGs to a lower quality, overwriting originals, in parallel).

  • Execute a command with arguments from a file, one argument per line:

    # list_of_ips.txt contains:
    # 192.168.1.1
    # 192.168.1.2
    
    xargs -a list_of_ips.txt -I {} ping -c 1 {}
    
  • Using xargs as a simple command builder (less common than find):

    echo "user1 user2" | xargs -I {} sudo userdel {}
    

    Deletes user1 and user2 using sudo userdel.

Gotchas

  • Whitespace and Special Characters: The biggest pitfall. By default, xargs splits input by whitespace and treats quotes and backslashes specially. This can break commands if your input items (like filenames) contain spaces or special characters. Always use find ... -print0 | xargs -0 ... when dealing with filenames.

  • -L vs -n: -L 1 reads one line at a time and passes it as arguments. -n 1 reads one item at a time and passes it as arguments. If a line has multiple items, -L 1 might pass the whole line, while -n 1 would pass only the first item.

  • Command Execution: xargs appends the arguments to the command you provide. If you want to insert arguments in the middle, you must use -I.

  • Empty Input: If xargs receives no input, it will not run the command by default. Use -r (or --no-run-if-empty) if you want to prevent execution when input is empty.

  • Shell Interpretation: xargs does not interpret shell metacharacters like *, ?, ~, etc., in the arguments it passes. If you need shell expansion, you often need to use eval (carefully!) or structure your command differently. For example, echo "*.txt" | xargs ls will list a file named "*.txt", not all text files. Use ls *.txt directly, or find . -name "*.txt" -exec ls {} \; or find . -name "*.txt" -print0 | xargs -0 ls.

  • Argument List Too Long: While xargs is designed to mitigate this by running commands multiple times, extremely long argument lists combined with other command-line options might still hit system limits. The -s flag can help control the maximum length, but it’s often better to rely on -n or -L and potentially -P for parallel processing.