Bash: Running command on quoted list of parameters using xargs

The typical usage for xargs is feeding it multiple lines of input, and having it run commands using each line as an argument.

But there are other cases when you have a single line separated by a delimiter or even a list of optionally quoted args, and I’ll show in this article how to handle those as well.

The most basic case is using xargs on multiple lines of input.  This is the basic case of taking each line and bookending it with BEGIN and END strings.

$ cat <<EOF > sep-by-lines.txt
> a
> b
> c
> one hundred
> two hundred
> EOF

$ cat sep-by-lines.txt | xargs -I {} echo BEGIN {} END

BEGIN a END
BEGIN b END
BEGIN c END
BEGIN one hundred END
BEGIN two hundred END

The next case is where you have a list of items, but this time they are all on a single line separated by a marker such as a comma.  You can set the delimiter with “-d”.

$ echo -n "a,b,c,one hundred,two hundred" > sep-by-commas.txt
$ cat sep-by-commas.txt | xargs -d ',' -I {} echo BEGIN {} END

BEGIN a END
BEGIN b END
BEGIN c END
BEGIN one hundred END
BEGIN two hundred END

But a much harder case is where you have a list of items all on a single line, but they are optionally quoted.  In this case it is not enough to set IFS, you need to parse with an awk pattern:

$ echo 'a b c "one hundred" "two hundred"' > quoted-params.txt
$ cat quoted-params.txt | awk 'BEGIN{FPAT = "([^[:space:]]+)|(\"[^\"]+\")"}{for(i=1;i<=NF;i++) print $i}' | xargs -I {} echo BEGIN {} END

BEGIN a END
BEGIN b END
BEGIN c END
BEGIN one hundred END
BEGIN two hundred END

 

REFERENCES

linux.die.net, man find

stackoverflow, FPAT solution by Inian

NOTES

simple xargs on files directly in folder

find . -maxdepth 1 -type f -name \*.txt | xargs -I {} echo BEGIN {} END

Find and xargs pair if there might be special chars

find . -maxdepth 1 -type f -name \*.txt -print0 | xargs --null -I {} echo BEGINTEXT {} ENDTEXT

Easier way to do single line with arguments separated by a delimiter

$ IFS=','; for i in $(cat sep-by-commas.txt); do echo BEGIN $i END; done

direct multiline heredoc  sent to xargs to be processed line by line

$ xargs -I {} echo BEGIN {} END << EOF
a
b
c
one hundred
two hundred
EOF