Xargs in Linux with bash -c and create a group of commands.
Xargs in Linux transforms standard input into command arguments. Put simply, it takes the output of one command and uses it as input for another.
This concept is the foundation of what makes xargs useful. Before diving into advanced techniques, let’s cover the basics.
Why use xargs?
Xargs helps you chain multiple operations into a single command line. Instead of writing complex shell scripts or functions, you can pipe data through xargs to get things done quickly.
The pattern I use with xargs follows three steps: List, Filter (optional), Action.
List
This is any command that produces a list of items. For example, ls -l or find returns a list of files and directories.
Filter
You can filter the list to get only the items you want. Commands like grep handle this. The filter step is optional — use it when you need to narrow down results. awk works well here too for extracting specific values.
Action
This is whatever you want to do with each item from the list. Any command that accepts the list items as parameters works here.
Here’s a concrete example: say you have images in a directory that you want to delete. You list them with find, filter them with a regex pattern on the filename, then run rm to delete them.
Comparing approaches
Let’s look at three ways to delete those files.
Manual approach: Go to the folder and delete each file one by one. This works but gets tedious with more than a few files.
Shell script with a FOR loop:
#!/bin/bash
# filter and get only image files with extension .png
FILES="./*.png"
for i in $FILES
do
echo "Deleting $i file..."
rm -f "$i"
done
Seven lines of code for a simple task. The loop isn’t complex, but writing a script for this feels like overkill.
Using xargs:
find . -name "*.png" | xargs rm
One line. Done.
You can add filtering:
find . -name "bitslovers-*.png" | xargs rm
Much simpler than the alternatives.
When to use xargs vs for loops
Xargs won’t work for every situation. Here’s when I reach for a FOR loop instead:
- You need to run multiple operations on the same item
- You need conditional logic before taking action
In those cases, a shell script with a FOR loop gives you more control.
Chaining commands
Xargs really shines when you pipe multiple commands together. There’s no limit to how many you can chain.
Example with three commands:
find . -name "*.png" | grep "bitslovers-" | xargs rm
Here’s a practical example — killing multiple processes:
ps aux | grep java | awk '{print $2}' | xargs kill
This finds all Java processes and kills them. The awk command extracts the process ID to pass to kill. Notice how you can chain multiple filters together with pipes.
How xargs works
At its core, xargs reads from standard input and executes a command using that input. Spaces and newlines act as delimiters, and blank lines get ignored.
But pipes have limitations. Sometimes you need to preprocess data into a format the next tool can handle.
Consider this scenario: trying to kill a background sleep process.
sleep 10000 &
pidof sleep
kill -9 $(pidof sleep)
The issue is that kill doesn’t accept piped input directly from ps or echo. That’s where xargs comes in:
sleep 10000 &
pidof sleep | xargs kill -9
Xargs takes the PID and passes it as an argument to kill. Problem solved.
Using the -I flag
The -I option lets you specify a replacement string for the input. This makes your commands more readable:
find . -name "*.log" | xargs -I {} mv {} /logs/
Here {} gets replaced with each filename. This pattern is useful when you need to reference the input multiple times.
Advanced: xargs with bash -c
Sometimes xargs alone isn’t enough. When you need to run multiple commands per input item, combine xargs with bash -c:
sleep 1000 &
pidof sleep | xargs -I{} bash -c "echo 'Killing PID {}'; kill -9 {}"
This runs two commands for each PID: prints a message, then kills the process. The key syntax is:
any_command | xargs -I{} bash -c "command1 {}; command2 {}"
Here’s a more complex example — performing three actions on each file:
echo 'BITSLOVERS' > file1
echo 'The best blog' > file2
echo 'Ever' > file3
mkdir backup
ls --color=never | grep -v backup | xargs -I{} bash -c "cat {}; mv {} backup; rm backup/{}"
This displays each file, moves it to backup, then deletes it from backup. The --color=never flag prevents color codes from messing up the parsing.
Tip: Always test your composite commands first by running them without the final bash -c to see what gets generated.
Conclusion
Xargs is one of those tools that makes the command line powerful. Once you get comfortable with the List-Filter-Action pattern, you’ll find yourself reaching for it constantly.
The bash -c combination unlocks even more possibilities. You can build complex pipelines without temporary files or elaborate scripts.
Combine xargs with commands like find, cp, and tar to handle file management tasks efficiently. For more details on xargs options, check man xargs or visit the xargs man page.
Have questions or feedback? Drop a comment below.
Thanks, Bits Lovers!
Comments