Dans bash
, je peux utiliser la substitution de processus et traiter la sortie d'un processus comme s'il s'agissait d'un fichier enregistré sur le disque:
$ echo <(ls)
/dev/fd/63
$ ls -lAhF <(ls)
lr-x------ 1 root root 64 Sep 17 12:55 /dev/fd/63 -> pipe:[1652825]
malheureusement, la substitution de processus n'est pas prise en charge dans dash
.
Quelle serait la meilleure façon d'émuler Process Substitution
en tiret?
Je ne veux pas enregistrer la sortie en tant que fichier temporaire quelque part ( /tmp/
), puis je dois le supprimer. Existe-t-il une alternative?
process-substitution
dash
Martin Vegter
la source
la source
bash
sur votre appareil?/dev/fd
et en utilisantxz -cd <file>
au lieu decat <file> | xz -d
) pourrait êtrexz -cd "$1" | { xz -cd "$2" | { diff /dev/fd/3 /dev/fd/4; } 3<&0; } 4<&0
.Réponses:
La question dans l'avis de prime actuel:
semble avoir une réponse ici .
Comme le montre la réponse de Gilles , l'idée générale est d'envoyer la sortie des commandes "producteur" à de nouveaux fichiers de périphérique 1 à différents stades d'un pipeline, en les mettant à la disposition des commandes "consommateurs", qui peuvent éventuellement prendre des noms de fichiers comme arguments ( en supposant que votre système vous donne accès aux descripteurs de fichiers en tant que
/dev/fd/X
).La façon la plus simple de réaliser ce que vous recherchez est probablement:
(Utiliser
file1.xz
à la place de"$1"
pour la lisibilité etxz -cd
au lieu decat ... | xz -d
car une seule commande suffit).La sortie de la première commande "producteur"
xz -cd file1.xz
, est dirigée vers une commande composée ({...}
); mais, au lieu d'être consommé immédiatement comme entrée standard de la commande suivante, il est dupliqué dans le descripteur de fichier3
et ainsi rendu accessible à tout ce qui se trouve dans la commande composée comme/dev/fd/3
. La sortie de la deuxième commande "producteur"xz -cd file2.xz
, qui ne consomme ni son entrée standard ni quoi que ce soit du descripteur de fichier3
, est ensuite dirigée vers la commande "consumer"diff
, qui lit à partir de son entrée standard et de/dev/fd/3
.La duplication de la tuyauterie et des descripteurs de fichiers peut être ajoutée afin de fournir des fichiers de périphérique pour autant de commandes "producteurs" que nécessaire, par exemple:
Bien que cela puisse ne pas être pertinent dans le contexte de votre question spécifique, il convient de noter que:
cmd1 <(cmd2) <(cmd3)
,cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
Et( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )
avoir des effets potentiels sur l'environnement d'exécution initial.Contrairement à ce qui se passe dans
cmd1 <(cmd2) <(cmd3)
,cmd3
etcmd1
danscmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0
ne pourra lire aucune entrée de l'utilisateur. Cela nécessitera d'autres descripteurs de fichiers. Par exemple, pour faire correspondrevous aurez besoin de quelque chose comme
1 Plus d'informations à ce sujet peuvent être trouvées sur U&L, par exemple dans Understanding / dev et ses sous-répertoires et fichiers .
la source
Vous pouvez reproduire ce que fait la coque sous le capot en faisant la plomberie manuellement. Si votre système a des entrées, vous pouvez utiliser le brassage des descripteurs de fichiers: vous pouvez traduire
/dev/fd/NNN
à
J'ai montré un exemple plus complexe pour illustrer plusieurs entrées et sorties. Si vous n'avez pas besoin de lire à partir de l'entrée standard et que la seule raison pour laquelle vous utilisez la substitution de processus est que la commande nécessite un nom de fichier explicite, vous pouvez simplement utiliser
/dev/stdin
:Sans , vous devez utiliser un canal nommé . Un canal nommé est une entrée de répertoire, vous devez donc créer un fichier temporaire quelque part, mais ce fichier n'est qu'un nom, il ne contient aucune donnée.
/dev/fd/NNN
la source
</dev/fd/8 >/dev/fd/9
ne sont pas équivalents à<&8 >&9
sous Linux et devraient y être évités.diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)
?Je pense que les canaux nommés sont plus simples à gérer que les redirections, donc en termes plus simples:
p1
etp2
sont des tuyaux nommés temporaires, ils peuvent être nommés n'importe quoi.Il serait plus intelligent de créer les tuyaux
/tmp
, par exemple dans un répertoire comme le montre la réponse de Gilles , et notez que vous n'avez pas besoincat
ici, donc:(Vous pourriez également vous en tirer sans les guillemets, car cela
mktemp
risque de créer de "beaux" noms de fichiers.)La solution de tuyau a la mise en garde que si la commande principale (
diff
) meurt avant de lire toutes les entrées, les processus d'arrière-plan peuvent rester suspendus.la source
Qu'en est-il de:
la source