Gelegentlich funktioniert die Prozessersetzung nicht wie erwartet. Hier ist ein Beispiel:
Eingang:
gcc <(echo 'int main(){return 0;}')
Ausgabe:
/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status
Eingang:
Aber es funktioniert wie erwartet, wenn es mit einem anderen Befehl verwendet wird:
grep main <(echo 'int main(){return 0;}')
Ausgabe:
int main(){return 0;}
Ich habe ähnliche Fehler bei anderen Befehlen festgestellt (dh der Befehl, der die Datei von der Prozessersetzung erwartet, kann nicht verwendet werden /dev/fd/63
oder ähnliches). Dieser Fehler gcc
ist nur der jüngste. Gibt es eine allgemeine Regel, die ich beachten sollte, um festzustellen, wann die Prozessersetzung auf diese Weise fehlschlägt und nicht verwendet werden sollte?
Ich benutze diese BASH-Version unter Ubuntu 12.04 (ich habe dies auch in Arch und Debian gesehen):
GNU bash, Version 4.3.11 (1) -release (i686-pc-linux-gnu)
illegal seek
sieht aus wie die Antwort - das|pipe
,bash
auf das das ausgeführte Programm zeigt, ist keine suchbare Datei. Wahrscheinlich, wenn Sieecho data | command /dev/fd/0
bei einem Programm nicht erfolgreich sein können, haben Sie ähnliches Glück w /<(cmd)
. Es wird keine Datei auf der Festplatte bereitgestellt. Es wird lediglich ein Argument ersetzt, das auf einen Pipe-Dateideskriptor verweist.gcc -xc <(echo 'int main(){return 0;}')
(was die SpracheC
explizit einstellt ).Antworten:
Die Prozessersetzung führt zu einer speziellen Datei (wie
/dev/fd/63
in Ihrem Beispiel), die sich wie das Leseende einer Named Pipe verhält. Diese Datei kann geöffnet und gelesen, aber nicht geschrieben, nicht gesucht werden.Befehle, die ihre Argumente als reine Streams behandeln, funktionieren, während Befehle, die erwarten, in Dateien zu suchen, die sie erhalten (oder in die sie schreiben), nicht funktionieren. Die Art des Befehls , dass Wille Arbeit ist das, was in der Regel einen Filter betrachtet wird:
cat
,grep
,sed
,gzip
,awk
, etc ... Ein Beispiel für einen Befehl, der nicht funktionieren ist ein Editor wievi
oder eine Dateioperation wiemv
.gcc
möchte in der Lage sein, auf seine Eingabedateien wahlfrei zuzugreifen, um festzustellen, in welcher Sprache sie geschrieben sind. Wenn Sie stattdessengcc
einen Hinweis auf die Sprache der Eingabedatei geben , ist es hilfreich, die Datei zu streamen:Die einfachere und einfachere Form ohne Prozessersetzung funktioniert auch:
Beachten Sie, dass dies nicht spezifisch für ist
bash
. Alle Shells, die die Prozessersetzung unterstützen, verhalten sich gleich.quelle
<()
Format sollte in jeder Hinsicht wie eine Datei wirken. Tatsächlich kenne ich keine Befehle, die eine Datei erwarten, mit der ich nicht zufrieden bin<()
. Diejenigen , die keine Arbeit tun , sind diejenigen , die Datei erwarten Namen , keine Dateien. Erwartet beispielsweisegrep -f
eine Datei und funktioniert einwandfrei mit<()
.<()
erzeugt eine Datei Namen (das Konstrukt erweitert , um/proc/self/fd/something
auf meinem System). Dieser Name verhält sich beim Öffnen wie das Leseende einer Named Pipe (S_IFIFO
) und nicht wie eine reguläre Datei (S_IFREG
), die unterstützt wird,read()
andere jedoch nichtseek()
.zsh
eine dritte Form der Prozessersetzung unterstützt wird, die zu diesem Zweck temporäre Dateien verwendet:gcc =(echo 'int main(){return 0;}')
<(echo '...')
aber nicht mit<(git show ...)
. eine Idee, warum das sein könnte?ld
(wodurch Objektformate erkannt werden ).-x
ist kein Hinweis; Es ist eine Erklärung. Wenn Sie dies angeben-x f95
, leitet GCC die Datei unabhängig von ihrem Namen oder Inhalt an den Fortran-95-Compiler weiter. Siehe gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Overall-Options.html