Що саме є <() в bash (і = () в zsh)?


36

Мені досить зручно з башем, але останнім часом я опинився на заміні, про яку не знав.

Що саме є <(<command>)в баші? Як воно порівнюється з =(<command>)в zsh?

Я розумію, що це стосується дескрипторів файлів за замовчуванням. У моєму комп’ютері

echo <()

повертається /proc/self/fd/11, що я виявив копію сценарію STDOUT, але це все ще здається мені досить заплутаним.

Відповіді:


51

Це називається процес заміщення.

<(list)Синтаксис підтримується обома, bashі zsh. Він забезпечує спосіб передачі виводу команди ( list) іншій команді, коли використання pipe ( |) неможливо. Наприклад, коли команда просто не підтримує введення STDINабо вам потрібен вихід декількох команд:

diff <(ls dirA) <(ls dirB)

<(list)з'єднує вихідний listфайл з файлом у /dev/fd, якщо його підтримує система, інакше використовується названа труба (FIFO) (що також залежить від підтримки системи; жодна інструкція не говорить про те, що станеться, якщо обидва механізми не підтримуються, імовірно, це припиняється з помилка). Потім ім'я файлу передається як аргумент у командному рядку.


zshдодатково підтримує =(list)як можливу заміну на <(list). З =(list)тимчасовим файлом використовується замість файлу у /dev/fdабо FIFO. Він може бути використаний як заміна, <(list)якщо програмі потрібно шукати висновок.

Відповідно до посібника ZSH, можуть бути й інші проблеми з тим, як <(list)працює:

=Форма корисна в якості як /dev/fdі названі реалізації труби <(...)мають свої недоліки. У першому випадку деякі програми можуть автоматично закрити відповідний дескриптор файлу перед вивченням файлу в командному рядку, особливо якщо це необхідно з міркувань безпеки, наприклад, коли програма працює із встановленням. У другому випадку, якщо програма насправді не відкриває файл, підпрограма, яка намагається прочитати або записати в трубку, (як правило, різні операційні системи можуть мати різну поведінку) блокується назавжди і повинна бути вбита явним чином . В обох випадках оболонка фактично постачає інформацію за допомогою труби, так що програми, які очікують, що з'явиться (див. Сторінку людини lseek(2)) у файлі, не працюватимуть.


Це допомогло мені зрозуміти, чому MacOS pfctl -f <(echo "pf rules")скаже поганий дескриптор файлу. використовуючи натомість zsh та = (відлуння "правил pf"), замість цього працює.
johnnyB

9

Зауважте, це баш відповідь, а не zsh.

У баші є випадки, коли не можна використовувати труби:

some_command | some_other_command

оскільки труби вводять підрозділи для кожного компонента трубопроводу, при виході підпакетів всі побічні ефекти, на які ви покладалися, зникнуть. Наприклад, цей надуманий приклад:

cat file | while read line; do ((count++)); done
echo $count

відобразиться порожній рядок, оскільки $countзмінна не існує в поточній оболонці.

Заміна процесу баш дозволяє уникнути цієї головоломки, дозволяючи читати з виводу "some_command", як і з файлу

while read line; do ((count++)); done < <(cat file)
# ....................................1.2
echo $count   # the variable *does* exist in the current shell

(1) - це звичайне перенаправлення входу. (2) - початок <()синтаксису заміщення процесу.


2
= (cmdlist) в zsh має майже такий же ефект, як <(cmdlist) у bash, але він створює (і видаляє, коли готовий) тимчасовий файл із висновком cmdlist для перенаправлення. Це добре, коли пошук потенційно робиться в програмі. <(cmdlist) також відомий zsh.
Gombai Sándor
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.