Czym dokładnie jest <() w bash (i = () w zsh)?

36

Jestem całkiem zadowolony z bash, ale ostatnio skończyłem na zmianie, której nie znałem.

Co dokładnie jest <(<command>)w bash? Jak to się ma do =(<command>)zsh w?

Rozumiem, że ma to związek z domyślnymi deskryptorami plików. Na moim komputerze

echo <()

zwraca /proc/self/fd/11, co okazało się być kopią skryptu STDOUT, ale nadal wydaje mi się to dość mylące.

Henrique Barcelos
źródło

Odpowiedzi:

51

Nazywa się to substytucją procesu.

<(list)Składnia jest obsługiwany przez obie, bashi zsh. Zapewnia sposób przekazania wyniku polecenia ( list) do innego polecenia, gdy użycie potoku ( |) nie jest możliwe. Na przykład, gdy polecenie po prostu nie obsługuje danych wejściowych STDINlub potrzebujesz wyniku wielu poleceń:

diff <(ls dirA) <(ls dirB)

<(list)łączy wyjście listz pliku w /dev/fd, jeśli jest obsługiwany przez system, w przeciwnym razie używany jest nazwany potok (FIFO) (co również zależy od obsługi przez system; żadna instrukcja nie mówi, co się stanie, jeśli oba mechanizmy nie są obsługiwane, prawdopodobnie przerywa to błąd). Nazwa pliku jest następnie przekazywana jako argument w wierszu poleceń.


zshdodatkowo obsługuje =(list)jak możliwy zamiennik <(list). Z =(list)pliku tymczasowego jest używany zamiast pliku w /dev/fdlub FIFO. Może być używany jako zamiennik, <(list)jeśli program musi szukać w danych wyjściowych.

Zgodnie z instrukcją ZSH mogą również występować inne problemy z <(list)działaniem:

=Forma jest przydatna zarówno jako /dev/fdi nazwany realizacja rura <(...)ma wady. W pierwszym przypadku niektóre programy mogą automatycznie zamknąć dany deskryptor pliku przed sprawdzeniem pliku w wierszu poleceń, szczególnie jeśli jest to konieczne ze względów bezpieczeństwa, na przykład gdy program działa w trybie setuid. W drugim przypadku, jeśli program nie otworzy pliku, podpowłoka próbująca czytać z potoku lub zapisywać do niego (w typowej implementacji różne systemy operacyjne mogą mieć różne zachowania) na zawsze blokuje się i musi zostać jawnie zabita . W obu przypadkach powłoka faktycznie dostarcza informacje za pomocą potoku, więc programy, które oczekują, że będą szukać (patrz strona lseek(2)podręcznika) w pliku, nie będą działać.

Adaefon
źródło
Pomogło mi to zrozumieć, dlaczego MacOS pfctl -f <(echo "pf rules")powiedziałby zły deskryptor pliku. zamiast tego działa zsh i = (echo „reguły pf”).
johnnyB,
9

Uwaga, to jest odpowiedź bash, nie zsh.

Są przypadki bash, w których nie można używać potoków:

some_command | some_other_command

ponieważ potoki wprowadzają podpowłoki dla każdego komponentu potoku, po wyjściu podpowłoki wszelkie efekty uboczne, na których polegałeś, zniknęłyby. Na przykład ten wymyślony przykład:

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

wyświetli pusty wiersz, ponieważ $countzmienna nie istnieje w bieżącej powłoce.

Podstawienie procesu bash pozwala uniknąć tej zagadki, umożliwiając czytanie z wyjścia „some_command” tak, jak z pliku

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

(1) to normalne przekierowanie wejścia. (2) jest początkiem <()składni podstawiania procesu.

Glenn Jackman
źródło
2
= (cmdlist) w zsh ma prawie taki sam efekt jak <(cmdlist) w bash, ale tworzy (i usuwa, gdy jest gotowy) plik tymczasowy z danymi wyjściowymi cmdlist dla przekierowania. Jest to dobre, gdy wyszukiwanie odbywa się w programie. <(cmdlist) jest również znany przez zsh.
Gombai Sándor