У меня есть следующий скрипт bash:
STDIN='&0'
if some-condition; then
STDIN=some-filename
fi
run-command <${STDIN}
Но это ошибки с &0: No such file or directory.
Аналогично для STDOUT.
Я пробовал использовать eval, но это тоже не сработало.
Что нужно сделать, чтобы это заработало?
&0 не является дескриптором файла. 0 — это дескриптор файла, который можно использовать в качестве «аргумента» для любого из отдельных операторов перенаправления < или <&.





STDIN='/dev/stdin' # Default to stdin
if some-condition; then
STDIN='some-filename'
fi
# Similarly, for STDOUT
STDOUT='/dev/stdout' # Default to stdout
if some-other-condition; then
STDOUT='some-other-filename'
fi
run-command <"$STDIN" >"$STDOUT"
Это хранение имен файлов, а не дескрипторов файлов. Кроме того, это зависит от окружающей среды. Не во всех средах, где можно найти Bash, предусмотрены /dev/stdin или /dev/stdout.
@JohnBollinger, Bash обрабатывает /dev/stdin и /dev/stdout (и /dev/stderr) специально при перенаправлениях. Что касается перенаправлений, они работают даже в системах, в которых нет файлов устройств /dev/stdin и /dev/stdout.
Справедливо, @pjs, но это по-прежнему имена файлов, а не дескрипторы файлов. Это имеет значение, поскольку они не используются одинаково.
«Дескриптор файла» — это просто номер дескриптора файла. В случае стандартного ввода это 0. В случае имени файла вы можете открыть имя файла, чтобы получить его дескриптор.
stdin=0
if some-condition; then
exec {stdin}<some-filename
fi
run-command <&"${stdin}"
Использование eval является злом. Не используйте его.
Предпочитайте переменные нижнего регистра для локальных переменных сценария.
Вы можете прочитать о exec {var}>file во втором абзаце документации bash https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Redirections.
Проверьте свои скрипты с помощью Shellcheck.
О файловых дескрипторах можно прочитать даже на вики https://en.wikipedia.org/wiki/File_descriptor .
Вы также можете, если вас не волнует исходный стандартный ввод, просто заменить его в зависимости от условия, что упростит задачу:
if some-condition; then
exec 0<some-filename
fi
run-command
exec 0<&- # close it if you want
Можно ли заменить STDIN для всей программы или его нужно заменить только для
run-command?