Just go with
foo | while read X; do bar "$X"; doneJust go with
foo | while read X; do bar "$X"; done grep stuff file.txt | while read key value ; do [ "$key" = "target" ] && found="$value" ; done
where you might expect $found to end up with the value for the line that has "target" in the first column. Then you notice that darn pipe symbol. The variable found is set in a subshell that terminates and the value is lost. This is a problem every time you need to keep some sort of state when looping. If you can tolate a bash-ism then you could do: while read key value ; do [ "$key" = "target" ] && found="$value" ; done < <(grep stuff file.txt)
but that doesn't read as nice and isn't compatible. It does avoid a common source of problems though, and might be worth getting into muscle memory for the times it is needed.is that a GNU v POSIX type of compatibility issue?
zsh should be bash compatible on this AFAIR
$ find /path -name "*.pdf" -print0 | xargs -0 -I {} echo "Processing: {}" # handles paths properly, obviates the need to write anything new whatsoever
Seriously kids, learn your tools and check yourself before you wreck yourselves writing tools that really, really don't need to be written.Try this with find and grep vs xargs. There's a big difference.
* in a lot of cases the performance just doesn't matter
* xargs gets you the spaces in filenames landmine
* some commands don't even support multiple target filename arguments
For scripts in long term use, yeah, sure, figure out xargs maybe. Any other situation with a "| while read" solution, especially on an interactive session, is an oddball and simplicity wins.
While it's true not every command supports multiple targets, presumably you know if you're using one of those commands.
Does whatever I'm piping into it though? It's "find" in maybe 30% of cases for me, no more, and null termination is not exactly common in other tools.
Considering the body of a while loop is more flexible too, I spend the brain capacity on remembering the details on that rather than xargs.
I'm well aware xargs is sometimes called for, but it's rare and when it happens I go look up the man page.
Ignorance of xargs gets you the landmine.
Understanding of xargs, helps you complete the mission without blowing off limbs.
$ find . -name "Some Files With Spaces*.txt" -print0 | xargs -0 -I {} echo "Processing: {}" # landmine avoided { # code that generates one item/filename per line of output } | { while read ITEM; do # do something with "$ITEM"; done; }
So I just tried this and it seems to work for a trivial case although you need 1 escape: enum() {
local source=$1; shift; local action=$1; shift
{ eval "$source" ; } | { while read ITEM; do eval "$action"; done; }
}
$ enum "find /tmp" "echo found: \$ITEM"
found: /tmp/.XIM-unix
found: /tmp/.ICE-unix printf 'silent data loss' | while read l; do printf '%s\n' "$l"; done
though at the point I need to write while IFS= read -r line || [ -n "$line" ]; do
printf '%s\n' "$line"
done
I'll use a different language.