Czasami podstawienie procesu nie będzie działać zgodnie z oczekiwaniami. Oto przykład:
Wkład:
gcc <(echo 'int main(){return 0;}')
Wydajność:
/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status
Wkład:
Ale działa zgodnie z oczekiwaniami, gdy jest używany z innym poleceniem:
grep main <(echo 'int main(){return 0;}')
Wydajność:
int main(){return 0;}
Zauważyłem podobne niepowodzenia w przypadku innych poleceń (tj. Polecenie oczekujące pliku z podstawienia procesu nie może używać /dev/fd/63
lub podobne). Ta awaria gcc
jest właśnie najnowsza. Czy istnieje jakaś ogólna zasada, o której powinienem wiedzieć, aby określić, kiedy proces podstawienia zakończy się niepowodzeniem w ten sposób i nie powinien być stosowany?
Używam tej wersji BASH na Ubuntu 12.04 (widziałem to również w arch i debian):
GNU bash, wersja 4.3.11 (1) -release (i686-pc-linux-gnu)
illegal seek
wygląda na to odpowiedź - w|pipe
którybash
wskazuje wykonywanego programu nie jest możliwy do przeszukania plików. prawdopodobnie jeśli nie uda ciecho data | command /dev/fd/0
się z programem, będziesz miał podobne szczęście w /<(cmd)
. Nie zapewnia pliku na dysku - po prostu zastępuje argument wskazujący deskryptor pliku potoku.gcc -xc <(echo 'int main(){return 0;}')
(coC
wyraźnie ustawia język ).Odpowiedzi:
W wyniku podstawienia procesu powstaje specjalny plik (jak
/dev/fd/63
w twoim przykładzie), który zachowuje się jak koniec odczytu nazwanego potoku. Ten plik można otworzyć i odczytać, ale nie można go zapisać, nie szukać.Polecenia, które traktują swoje argumenty jako czyste strumienie, działają, natomiast polecenia, które oczekują, że będą szukać w plikach, które zostały im przekazane (lub do nich piszą), nie będą działać. Rodzaj polecenia, że praca będzie to co uważa się zwykle za filtrem:
cat
,grep
,sed
,gzip
,awk
, itd ... Przykładem polecenia, które nie będzie działać to edytor podobnyvi
lub operacja plik podobnymv
.gcc
chce mieć możliwość losowego dostępu do swoich plików wejściowych w celu wykrycia języka, w którym są zapisane. Jeśli zamiast tegogcc
podpowiesz, jaki jest język pliku wejściowego, z przyjemnością przesyłasz plik:Działa również prostsza, bardziej prosta forma bez podstawiania procesów:
Pamiętaj, że nie jest to specyficzne dla
bash
. Wszystkie powłoki obsługujące podstawianie procesów zachowują się w ten sam sposób.źródło
<()
Format powinien działać jak plik dla wszystkich zamiarów i celów. W rzeczywistości nie znam żadnych poleceń, które oczekują, że plik nie będzie zadowolony<()
. Te, które nie działają, oczekują nazw plików , a nie plików. Na przykładgrep -f
oczekuje pliku i działa dobrze z<()
.<()
tworzy nazwę pliku (konstrukcja rozwija się/proc/self/fd/something
w moim systemie). Ta nazwa po otwarciu działa jak koniec odczytu nazwanego potoku (S_IFIFO
), a nie zwykły plik (S_IFREG
), który obsługujeread()
i inne, ale nieseek()
.zsh
obsługuje trzecią formę podstawiania procesów, która wykorzystuje pliki tymczasowe specjalnie do tego celu:gcc =(echo 'int main(){return 0;}')
<(echo '...')
ale nie z<(git show ...)
. jakiś pomysł, dlaczego to może być?ld
(który wykrywa formaty obiektów).-x
nie jest wskazówką; to jest deklaracja. Jeśli określisz-x f95
, GCC przekaże plik do kompilatora Fortran-95 bez względu na jego nazwę lub zawartość. Widzieć gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Overall-Options.html