Qual é a diferença entre "$ (arquivo cat)", "$ (<arquivo)" e "leia ... <arquivo" para arquivos com uma linha?

Eu tenho um arquivo de entrada que contém apenas uma linha:

$ cat input
foo bar

Quero usar esta linha no meu script e existem três maneiras de obtê-lo que eu conheço:

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

Por exemplo, usar substituição de comando significa gerar um subshell, enquanto que comread Eu não, correto? Que outras diferenças existem e há uma maneira preferida em relação às outras? Eu também notei (comstrace) que apenasread aciona o syscallopenat por algum motivo. Como é possível que os outros não?

$ 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

questionAnswers(1)

yourAnswerToTheQuestion