The mechanics of this shell syntax: ${1:-$(</dev/stdin)}

  1. $(..): from bash manual is a command substitution not process substitution <(..). and from Command substitution

The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).

  1. /dev/stdin is a symlink to /proc/self/fd/0, convenient here because of $(<..) syntax which expects a file.

  2. this could cause a problem because the command may be blocked until stdin closed. it is safe in the meaning that multiline input will be preserved because au double-quotes.

Finally creating a pipe and forking a process (like in mv -v foo.ext bar.ext | log) for each log command may be inefficient.


Answering your questions

  • You have confused the syntax between using process substitution which takes the syntax of <(cmd) and simple shell re-direction < file. In plain form, < basically is to read from the standard input and > to write to standard output. The syntax < file is a short-hand syntax to put the contents of the file made available on the standard input which can be read by the commands.
  • So when you run cat < file, it basically puts the content of the file in standard input file descriptor which is later than read by the cat process. The advantage of using $(<file) would be the shell doesn't have fork an external process cat and just use its own mechanism to read the file content.
  • The $(..) is a syntax for command-substitution where command is run in a sub-shell environment and $(..) is replaced with the standard output of the command. For a special case of "$(<file)" i.e. without any commands and only re-directions involved, the shell instead of reading from the standard input starts reading from the start of the file and puts the result on the standard output.