¿Cuál es la diferencia entre "$ (archivo cat)", "$ (<archivo)" y "leer ... <archivo" para archivos con una línea?

Tengo un archivo de entrada que contiene solo una línea:

$ cat input
foo bar

Quiero usar esta línea en mi script y hay 3 formas de obtenerla que conozco:

line=$(cat input)
line=$(<input)
IFS= read -r line < input

Por ejemplo, usar la sustitución de comandos significa que engendro una subshell, mientras que conread Yo no, ¿correcto? ¿Qué otras diferencias hay y se prefiere una forma sobre las otras? También me di cuenta (constrace) solamente esoread activa la syscallopenat por alguna razón. ¿Cómo es posible que los demás no lo hagan?

$ strace ./script |& grep input
read(3, "#!/usr/bin/env bash\n\ncat > input"..., 80) = 80
read(255, "#!/usr/bin/env bash\n\ncat > input"..., 167) = 167
read(255, "\nline=$(cat input)\nline=$(<input"..., 167) = 60
read(255, "line=$(<input)\nIFS= read -r line"..., 167) = 41
read(255, "IFS= read -r line < input\n", 167) = 26
openat(AT_FDCWD, "input", O_RDONLY)     = 3

Respuestas a la pregunta(1)

Su respuesta a la pregunta