I recently came across this really neat syntax, in the context of creating bash
functions which can accept an argument or a stream from STDIN (i.e. can be piped to). On the surface, I understand what's happening here, but I'd like a bit more explanation of the actual mechanics of how this is working.
Here's the syntax (as per the title): ${1:-$(</dev/stdin)}
And in context, one might use it as:
log(){
echo -e >&1 "INFO: ${1:-$(</dev/stdin)}"
}
Allowing the following usage:
$ log foo
INFO: foo
Alternatively, you could also do this
mv -v foo.ext bar.ext | log
INFO: renamed 'foo.ext' -> 'bar.ext'
This is great because its the single most concise method I've seen for enabling both argument and pipe functionality with bash
functions (I forget where I came across it now, unfortunately).
Now, I understand (or think I understand), most of what's happening here at least superficially, but I'd appreciate a deeper understanding. Here's how I interpret it, followed by my remaining questions:
${1:-$(</dev/stdin)}
${1}
is obviously the default argument that a function accepts${1:-x}
is a variable/brace expansion 'fall back' to the string'x'
if$1
is otherwise empty (or unset?). In this case falling back to the STDIN process sub.$()
is obviously aprocesscommand substitution- and finally,
</dev/stdin
is obviously a redirect from standard input which allows the pipe to work at all.
This essentially says if $1
isn't populated by an argument, fall back to using STDIN - which I'm happy with conceptually.
So here are my questions:
- I've never seen a redirect (
<
) inside aprocesscommand substitution, without an actual command preceding it (e.g.$(cat < somefile.ext)
). So what is actually happening (the nitty-gritty) when theprocesscommand substitution receives the redirect with no other command to invoke? - Why is it necessary to wrap the STDIN redirect in a
processcommand substitution at all? (actually, as I write this it occurs to me I haven't tested it without, but I'll keep it simple). - Is this safe? I've used it with multiline STDIN, and it hasn't broken so far. Where might this fall down (if anywhere?).
log
) and one for logging piped input (log_pipe
or whatever). – Howzell