1. Overview

Many Linux commands support both standard input (Stdin) and command arguments, such as sed, grep, and awk.

On the other hand, some commands don’t read Stdin and only support arguments – for example, cp, rm, and mv. So, when we want to execute these commands with Stdin as the input, we need to convert Stdin into arguments. The xargs command is born to do that.

In this tutorial, we’ll learn how to use the xargs command to handle multiple arguments.

2. Two Types of Commands Using Multiple Arguments

Commands can have multiple arguments in two scenarios:

  • All command arguments – COMMAND ARG1 ARG2 ARG3
  • Option arguments – for example, COMMAND -a ARG1 -b ARG2 -c ARG3

In this tutorial, we’ll address how to use xargs to handle multiple arguments, and of course, we will cover both scenarios.

3. All Command Arguments

3.1. The threeWords.sh Script

First of all, let’s create a simple shell script to simulate a command requiring three arguments:

$ cat threeWords.sh
#!/bin/bash
if [[ "$#" != 3 ]]; then
    echo "[Error] Three arguments required."
    exit 1
fi

echo "The 1st argument is $1"
echo "The 2nd argument is $2"
echo "The 3rd argument is $3"

As the cat output above shows, the threeWords.sh script just prints the three arguments individually.

3.2. Passing Three Arguments to the Script

Since the three arguments’ positions are contiguous, it’s not a challenge for xargs:

$ echo "Tom Likes Jerry" | xargs ./threeWords.sh 
The 1st argument is Tom
The 2nd argument is Likes
The 3rd argument is Jerry

The xargs command can convert Stdin into arguments. Also, it allows us to use placeholders to insert the arguments into the required positions. However, it isn’t an easy task for xargs if we want to make further adjustments to the arguments, such as reordering the arguments from Stdin. For example, we might like to pass “Jerry” as the first argument and “Tom” as the third.

One way to solve it is we process the data before we hand it over to xargs:

$ echo "Tom Likes Jerry" | awk '{ print $3, $2, $1 }' | xargs ./threeWords.sh
The 1st argument is Jerry
The 2nd argument is Likes
The 3rd argument is Tom

As the example above shows, before we pass the data to xargs, we ask awk to reorder the arguments.

4. Option Arguments

4.1. Two Option Styles

According to argument syntax conventions, there are two types of options:

  • POSIX options such as -o and -o ARG
  • Long options such as –option and –option=ARG

As we can see, both option types can have arguments. The xargs command follows the same rule to pass arguments to options regardless of the options styles.

Therefore, in this tutorial, we will take the POSIX option style as an example.

4.2. The threeOptions.sh Script

Again, let’s create a shell script to accept three options with arguments:

$ cat threeOptions.sh
#!/bin/bash

while getopts ":A:B:C:" opt; do
  case $opt in
   A) echo "The argument for the option A is $OPTARG" ;;
   B) echo "The argument for the option B is $OPTARG" ;;
   C) echo "The argument for the option C is $OPTARG" ;;
   ?) echo "Unknown Option" 
      exit 1 ;;
  esac
done
shift "$(($OPTIND -1))"

In the script threeOptions.sh, we’ve used getopts to parse options and their arguments.

4.3. Passing Arguments to the Script

This time, the arguments are not contiguous.

Further, we know that, usually, the options’ order won’t influence the command execution. That is to say, we need to index the arguments somehow to inject the arguments into the correct positions freely.

As we’ve mentioned earlier, xargs cannot adjust the arguments. However, we’ve learned the command echo “Tom Likes Jerry” | xargs a_shell_script will pass three arguments to “a_shell_script“. Of course, in “a_shell_script“, we can do whatever we want to the three arguments.

Therefore, we can wrap the actual command or script in “a_shell_script” to accept and adjust the arguments from the xargs command.

The easiest way to do that would be bash -c ‘the_real_command -a arg1 -b arg2 …’.

We need to keep in mind that if we use bash -c ‘the_real_command ..”, the first argument is assigned to $0 instead of $1.

Next, let’s see if our idea will solve the problem:

$ echo "Tom Likes Jerry" | xargs bash -c './threeOptions.sh -A $0 -B $1 -C $2'
The argument for the option A is Tom
The argument for the option B is Likes
The argument for the option C is Jerry

Since the arguments have been indexed, we can easily change the arguments’ order or decide which argument to pass to which option.

Let’s say we want to pass “Jerry” to option “A” and assign “Tom” to option “C“:

$ echo "Tom Likes Jerry" | xargs bash -c './threeOptions.sh -A $2 -B $1 -C $0'
The argument for the option A is Jerry
The argument for the option B is Likes
The argument for the option C is Tom

So, we’ve solved the problem.

5. Conclusion

xargs can help us convert input from Stdin into the arguments to a command.

In this article, we’ve addressed using xargs to handle multiple arguments to commands through examples.