Я хотел бы понять, куда идет перенаправление стандартного ввода в таком выражении, как < <(cmd)
в качестве теста, чтобы узнать больше о bash, я попытался написать функцию bash с помощью while .. do .. done
, и чтобы она заработала, мне пришлось использовать метод проб и ошибок, в основном потому, что я не знал поведения или первого перенаправления в < <(find ...)
:
while read L ;do basename "$L";((k++));done < <(
find -maxdepth 1 -type d -name '.*' |
sort
)
Только с <(find ...
не работает. Я полагаю, это потому, что стандартный вывод командной строки find
переходит в файл tmp (я так читал); поэтому я добавил еще один <
, чтобы «протолкнуть» дальше копию stdout . Это я могу понять, но как я могу знать, что стандартный вывод, скопированный в файл tmp, не останавливается на первой встреченной команде: basename
и доходит до стандартного ввода команды while
?
Все внутри цикла while
наследует стандартный ввод цикла как свой собственный, поэтому каждая команда read
также считывается из подстановки процесса.
<(...)
сам по себе является заменой процесса. Он ведет себя как имя файла, за исключением того, что «содержимое» файла, который он называет, является выводом команды. Например,
$ echo <(echo foo)
/dev/fd/63
$ cat <(echo foo; echo bar)
foo
bar
Цикл while
не принимает аргументов, поэтому вы получаете синтаксическую ошибку без перенаправления ввода.
$ while read x; do echo "$x"; done <(echo foo; echo bar)
bash: syntax error near unexpected token `<(echo foo; echo bar)'
При перенаправлении ввода цикл while
(который является командой и, как и любая другая команда, имеет собственный стандартный ввод) использует подстановку процесса в качестве стандартного ввода.
$ while read x; do echo "$x"; done < <(echo foo; echo bar)
foo
bar
while
на самом деле не использует свой стандартный ввод, но любая команда в цикле while
наследует свой стандартный ввод из цикла. Это включает read
, поэтому каждое выполнение read
получает другую строку из файла до тех пор, пока файл не будет исчерпан, после чего read
имеет статус выхода 1 и цикл завершается.
как далеко заходит перенаправление в командной строке?
Перенаправление действует на протяжении всей команды, к которой оно применяется.
Существует грамматика оболочки, которая определяет основные вещи, находящиеся внутри «командной строки». Вы можете ознакомиться с стандартом оболочки POSIX и документацией по Bash.
Команда является одной из следующих:
Simple command (see Simple Commands) Pipeline (see Pipelines) List compound-list (see Lists) Compound command (see Compound Commands) Function definition (see Function Definition Command)
Команда может быть составной командой, которая может быть конструкцией цикла, которая может быть конструкцией цикла while
. while
— это одна команда.
Перенаправление перенаправляется на протяжении всей команды и наследуется для любых команд внутри этой команды.
while
redirected here
do
redirected here
done < redirection
if
redirected here
then
redirected here
else
redirected here
fi < redirection
etc.
<(...)
само по себе не является перенаправлением; это замена процесса, которая предоставляет вывод команды, как если бы это был файл.<
междуdone
и подстановкой процесса является оператором перенаправления: он заставляет циклwhile
использовать подстановку процесса в качестве стандартного ввода.