Execute a command once per line of piped input?

The accepted answer has the right idea, but the key is to pass xargs the -n1 switch, which means "Use at most 1 argument per command line":

cat file... | xargs -n1 command

Or, for a single input file you can avoid the pipe from cat entirely and just go with:

<file xargs -n1 command

Updated 2020-08-05:

I would also like to respond to the advice found in user Jander's comment, which was heavily upvoted, despite containing some amount of misinformation as I will now explain.

Do not be so hasty to recommend the -L option of xargs, without mentioning the trouble that its trailing blank(s) (so called) feature can lead to. In my opinion this switch causes more harm than good and is certainly a stretch to use to mean, for the case of -L 1, act on one non-empty line at a time. To be fair, the man page for xargs does spell out the features (read as: issues) that come with the -L switch.

Since Jander made no mention of the issues when mentioning -L to perhaps a hasty unsuspecting StackOverflow audience seeking quick tips and not having the time for such tedious things as reading man pages rather than accepting comments and answers as gospel, I will now present my case for why -L is a very bad suggestion without a careful understanding of all of the baggage that it brings along for the ride.

In order to demonstrate my disdain for -L, let me present a simple input file called mynumbers.txt that consists of the following text:

1
2␠
3

Because of the fact that the line that contains the digit 2 has a space character (shown as a Unicode SYMBOL FOR SPACE glyph after the digit 2 in the preceding code, in case your browser's font does not have a visual representation for this Unicode character), a command that uses xargs -L1, such as:

<mynumbers.txt xargs -L1 echo

..., would produce the following (perhaps surprising) output:

1
2 3

This is caused by the fact that the -L switch instructs xargs to append subsequent lines to those that end with blanks, a behavior that may only effect the resulting output in those oddball moments where lines are not properly trimmed of trailing blanks - a time bomb bug waiting for the right input file to present itself.

On the other hand, the same command using the -n 1 switch of xargs, instead of -L 1 would produce a far more acceptable output of:

1
2␠
3

Even more surprisingly, perhaps, is that the -L switch unlike -n forces the -x option of xargs to go into effect. This causes termination of the xargs process if a command line is encountered that it deems too long for the environment on which it is run.

An input file consisting of many lines with trailing blanks in succession could potentially cause xargs to terminate midstream if the concatenation of all of these into one superline exceeds xargs' definition of too long for a command line - a size determined by xargs based on the max length specified for the platform on which it is run and further offset based on a seemingly arbitrary constant (remember those pesky indefinite integrals from Calculus and losing a point on a quiz/test or two, because you forgot to write + C after your solution to the integral?) as explained in more detail in the man page.

A -n value of 1, on the hand, would just chop up the lines into (hopefully) small bite sized one-line chunks and execute the command supplied to xargs with them, one at a time, without any weight given to whether they end with blanks or not.

An additional note regarding the xargs man page: I don't know why the ambiguous and non-standard word blanks was used throughout the xargs man page, instead of far better defined and less ambiguous options such as:

  • space(s), if blanks means one or more ASCII space characters
  • whitespace(s) other than new-lines (if that's what blanks really means)
  • one or more non-printable characters from the set: {space, horizontal tab} (if this is what led to the use of blanks as a seemingly good illustrative choice)

In Bash or any other Bourne-style shell (ash, ksh, zsh, …):

while read -r line; do command "$line"; done

read -r reads a single line from standard input (read without -r interprets backslashes, you don't want that). Thus you can do either of the following:

$ command | while read -r line; do command "$line"; done  

$ while read -r line; do command "$line"; done <file

That's what xargs does.

... | xargs command

Tags:

Shell

Bash

Fish