Я (как и все остальные, похоже) немного запутался в том, какая именно цель здесь, поэтому я дам три возможных ответа, которые могут охватить то, что вы действительно хотите. Во-первых, относительно простая цель - заставить скрипт читать из списка файлов (предоставленных в командной строке) или из стандартного stdin:
if [ $# -gt 0 ]; then
exec < <(cat "$@")
fi
# From this point on, the script's stdin is redirected from the files
# (if any) supplied on the command line
Примечание. Использование $ @ в двойных кавычках - лучший способ избежать проблем с забавными символами (например, пробелами) в именах файлов - $ * и без кавычек $ @ оба приводят в замешательство. Используемый здесь трюк <() предназначен только для bash; он запускает cat в фоновом режиме для подачи данных из файлов, предоставленных в командной строке, а затем мы используем exec для замены stdin скрипта на вывод из cat. </p>
... но это, кажется, не то, что вы на самом деле хотите. То, что вы действительно хотите - это передать предоставленные имена файлов или stdin скрипта в качестве аргументов команде внутри скрипта. Это требует своего рода обратного процесса: преобразование стандартного сценария в файл (фактически именованный канал), имя которого можно передать команде. Как это:
if [[ $# -gt 0 ]]; then
command "$@" <<EOF
here-doc goes here
EOF
else
command <(cat) <<EOF
here-doc goes here
EOF
fi
Используется <() для запуска stdin скрипта через cat в именованный канал, который затем передается команде в качестве аргумента. Между тем, командный стандарт взят из Here-Doc. </p>
Теперь, я думаю, это то, что вы хотите сделать, но это не совсем то, что вы просили, то есть оба перенаправить ввод скрипта из предоставленных файлов и передать stdin команде внутри скрипта. Это может быть сделано путем объединения вышеперечисленных методов:
if [ $# -gt 0 ]; then
exec < <(cat "$@")
fi
command <(cat) <<EOF
here-doc goes here
EOF
... хотя я не могу понять, почему вы действительно хотите это сделать.