Not sure I see the point of this. Remembering a bunch of options on one tool is no better than a bunch of tools/constructs? Especially if the latter are useful elsewhere. And it can't be used for scripts unless you start shipping it alongside, which… nah.
Just go with
foo | while read X; do bar "$X"; doneWhile FTW! I just wondered whether it could be simplified because I get a bit tired of typing out my own belt and braces version of it:
{ # 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-unixI use "| while read" as well, because it works well in a pipeline and handles embedded spaces. It doesn't handle embedded newlines, but in practice, real files have embedded spaces, while embedded newlines only happen in test cases and exploits. (You can do actual NUL-delimited reads with `-d ''`, but for a quick command-line operation that's generally not necessary, and if you're going to be that careful you probably also need `-r`.)
Depending on the actual command, this can be far slower and less efficient than xargs. You're creating a separate process for each invocation of bar when a lot of commands will take many targets for a single invocation.
Try this with find and grep vs xargs. There's a big difference.
I just use while’s default variable name, $REPLY most of the time. But `while` is my preferred tool for the xargs problem in most cases.
Bash while loops are pretty readable and the above would be a nice to iterate over lines if it wasn't for that gnarly pipe, which is a common source of errors in this construct. Remember that a pipe starts a new shell. So:
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: 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.