Parfois, la substitution de processus ne fonctionnera pas comme prévu. Voici un exemple:
Contribution:
gcc <(echo 'int main(){return 0;}')
Sortie:
/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status
Contribution:
Mais cela fonctionne comme prévu lorsqu'il est utilisé avec une commande différente:
grep main <(echo 'int main(){return 0;}')
Sortie:
int main(){return 0;}
J'ai remarqué des échecs similaires avec d'autres commandes (c'est-à-dire que la commande qui attend le fichier de la substitution de processus ne peut pas utiliser /dev/fd/63
ou similaire). Cet échec avec gcc
n'est que le plus récent. Existe-t-il une règle générale que je devrais connaître pour déterminer quand la substitution de processus échouera de cette manière et ne devrait pas être utilisée?
J'utilise cette version BASH sur Ubuntu 12.04 (j'ai également vu cela dans arch et debian):
GNU bash, version 4.3.11 (1) -release (i686-pc-linux-gnu)
illegal seek
ressemble à la réponse - celui|pipe
quibash
pointe le programme exécuté n'est pas un fichier recherché. probablement si vous ne pouvez pas réussirecho data | command /dev/fd/0
un programme, vous aurez une chance similaire avec<(cmd)
. Il ne fournit pas de fichier sur disque - il remplace simplement un argument qui pointe vers un descripteur de fichier pipe.gcc -xc <(echo 'int main(){return 0;}')
(qui définitC
explicitement la langue ).Réponses:
La substitution de processus entraîne un fichier spécial (comme
/dev/fd/63
dans votre exemple) qui se comporte comme l'extrémité en lecture d'un canal nommé. Ce fichier peut être ouvert et lu, mais pas écrit, pas recherché.Les commandes qui traitent leurs arguments comme de purs flux fonctionnent tandis que les commandes qui s'attendent à rechercher dans les fichiers qui leur sont donnés (ou à y écrire) ne fonctionneront pas. Le genre de commande qui fonctionnera est ce qui est généralement considéré comme un filtre:
cat
,grep
,sed
,gzip
,awk
, etc ... Un exemple d'une commande qui ne fonctionnera pas est un éditeur commevi
ou une opération de fichier commemv
.gcc
souhaite pouvoir effectuer un accès aléatoire sur ses fichiers d'entrée pour détecter dans quelle langue ils sont écrits. Si vous donnez plutôtgcc
un indice sur la langue du fichier d'entrée, il est heureux de diffuser le fichier:La forme plus simple et plus simple sans substitution de processus fonctionne également:
Notez que cela n'est pas spécifique à
bash
. Tous les shells qui prennent en charge la substitution de processus se comportent de la même manière.la source
<()
format doit agir comme un fichier à toutes fins utiles. En fait, je ne connais pas de commandes qui attendent un fichier qui ne sera pas satisfait<()
. Ceux qui ne fonctionnent pas sont ceux qui attendent des noms de fichiers , pas des fichiers. Par exemple,grep -f
attend un fichier et fonctionne correctement avec<()
.<()
un nom de fichier (la construction se développe/proc/self/fd/something
sur mon système). Ce nom, lorsqu'il est ouvert, agit comme l'extrémité de lecture d'un tube nommé (S_IFIFO
) plutôt que d'un fichier normal (S_IFREG
) dans lequel il est pris en chargeread()
et d'autres mais passeek()
.zsh
prend en charge une troisième forme de substitution de processus qui utilise des fichiers temporaires spécialement à cet effet:gcc =(echo 'int main(){return 0;}')
<(echo '...')
mais pas avec<(git show ...)
. une idée pourquoi cela pourrait être?ld
(qui détecte les formats d'objet).-x
n'est pas un indice; c'est une déclaration. Si vous spécifiez-x f95
, GCC transmettra le fichier au compilateur Fortran-95 indépendamment de son nom ou de son contenu. Voir gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Overall-Options.html