Votre union magique est un point-virgule ... et des accolades:
{ cat wordlist.txt ; ls ~/folder/* ; } | wc -l
Les accolades ne regroupent que les commandes, de sorte que le signe de canal |affecte la sortie combinée.
Vous pouvez également utiliser des parenthèses ()autour d'un groupe de commandes pour exécuter les commandes d'un sous-shell. Cela a un ensemble subtil de différences avec les accolades, par exemple, essayez ce qui suit:
cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd
Vous verrez que toutes les variables d'environnement, y compris le répertoire de travail en cours, sont réinitialisées après la sortie du groupe de parenthèses, mais pas après le groupe d'accolades.
En ce qui concerne le point-virgule, les variantes incluent les signes &&et ||, qui exécuteront la deuxième commande de manière conditionnelle uniquement si la première a abouti ou si, dans la négative, par exemple,
cd $HOME/project && make
ls $HOME/project || echo "Directory not found."
Ça marche! Aidez-moi à apprendre - que font exactement les accolades ici? Quels autres pouvoirs magiques ont-ils?
David Oneill
@DavidOneill { list; }est une commande composée . De bash(1): la liste est simplement exécutée dans l'environnement shell actuel. La liste doit se terminer par un saut de ligne ou un point-virgule. [..] Le statut de retour est le statut de sortie de la liste.
Lekensteyn
J'ai ajouté un peu plus d'informations à la réponse. Le guide définitif pour les scripts shell avec bash est la page de manuel bash, tapez à man bashpartir de la ligne de commande et parcourez-la.
Pablomme
devrait le; dans ces commandes, ne pas être && si le fichier wordlist.txt n’existe pas?
Rinzwind
S'il wordlist.txtn'existe pas, une erreur de catapparaîtra sur l'erreur standard, mais pas sur la sortie standard, wc -lelle ne comptera donc aucune ligne. Même chose pour ~/folderne pas exister. On pourrait ajouter 2> /dev/nullentre chacune de ces commandes et leur point-virgule pour éviter les parasites sur les erreurs standard, mais les messages d'erreur ne sont pas moche, mais sont sans danger pour le comptage des lignes.
Pablomme
8
Etant donné qu’il wcaccepte un chemin de fichier en entrée, vous pouvez également utiliser la substitution de processus:
Remarquez que ls ~/folder/*le contenu des sous-répertoires est également renvoyé, le cas échéant (en raison de l’expansion globale). Si vous voulez juste lister le contenu de ~/folder, utilisez simplement ls ~/folder.
Le wc -létait juste un composé par exemple, je suis réellement tuyauterie en quelque chose de plus compliqué qui ne dispose pas de cette option.
David Oneill
2
@DavidOneill Eh bien, comme cataccepte un argument de fichier, vous pouvez utiliser cat <(cat wordlist.txt; ls wordlist.txt) | wc -let même cat wordlist.txt <(ls wordlist.txt) | wc -l. C’est bien sûr très moche, mais cela démontre les possibilités infinies des outils en ligne de commande.
Lekensteyn
1
@DavidOneill Correct, je l'ai corrigé maintenant, merci.
Lekensteyn
1
Vous voulez ls ~/folder/que if ~/foldersoit un lien symbolique lsrépertorie le contenu de sa cible au lieu du lien lui-même. Soit dit en passant, toutes les lscommandes doivent être suivies de -1manière à ce qu'un seul fichier par ligne soit imprimé, ce qui wc -lconstitue un moyen valable de compter les fichiers.
Pablomme
@pablomme Vous êtes vrai à propos du lien symbolique, mais cela -1est implicite, car la sortie n'est pas un terminal, mais un tuyau.
Lekensteyn
2
Je me posais la même question et j'ai fini par écrire un court script.
magicalUnionThing(Je l'appelle append):
#!/bin/sh
cat /dev/stdin
$*
Rendre ce script exécutable
chmod +x ./magicalUnionThing
Maintenant tu fais
cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l
Ce qu'il fait:
Envoyer une entrée standard vers une sortie standard
Exécuter l'argument. $*renvoie tous les arguments sous forme de chaîne. La sortie de cette commande va par défaut à la sortie standard du script.
Ainsi, la sortie standard de magicalUnionThing sera sa sortie stdin + stdout de la commande transmise en tant qu'argument.
Il existe bien sûr des moyens plus simples, comme indiqué dans les autres réponses.
Peut-être que cette alternative peut être utile dans certains cas.
{ list; }
est une commande composée . Debash(1)
: la liste est simplement exécutée dans l'environnement shell actuel. La liste doit se terminer par un saut de ligne ou un point-virgule. [..] Le statut de retour est le statut de sortie de la liste.man bash
partir de la ligne de commande et parcourez-la.wordlist.txt
n'existe pas, une erreur decat
apparaîtra sur l'erreur standard, mais pas sur la sortie standard,wc -l
elle ne comptera donc aucune ligne. Même chose pour~/folder
ne pas exister. On pourrait ajouter2> /dev/null
entre chacune de ces commandes et leur point-virgule pour éviter les parasites sur les erreurs standard, mais les messages d'erreur ne sont pas moche, mais sont sans danger pour le comptage des lignes.Etant donné qu’il
wc
accepte un chemin de fichier en entrée, vous pouvez également utiliser la substitution de processus:Cela équivaut à peu près à:
Remarquez que
ls ~/folder/*
le contenu des sous-répertoires est également renvoyé, le cas échéant (en raison de l’expansion globale). Si vous voulez juste lister le contenu de~/folder
, utilisez simplementls ~/folder
.la source
wc -l
était juste un composé par exemple, je suis réellement tuyauterie en quelque chose de plus compliqué qui ne dispose pas de cette option.cat
accepte un argument de fichier, vous pouvez utilisercat <(cat wordlist.txt; ls wordlist.txt) | wc -l
et mêmecat wordlist.txt <(ls wordlist.txt) | wc -l
. C’est bien sûr très moche, mais cela démontre les possibilités infinies des outils en ligne de commande.ls ~/folder/
que if~/folder
soit un lien symboliquels
répertorie le contenu de sa cible au lieu du lien lui-même. Soit dit en passant, toutes lesls
commandes doivent être suivies de-1
manière à ce qu'un seul fichier par ligne soit imprimé, ce quiwc -l
constitue un moyen valable de compter les fichiers.-1
est implicite, car la sortie n'est pas un terminal, mais un tuyau.Je me posais la même question et j'ai fini par écrire un court script.
magicalUnionThing
(Je l'appelleappend
):Rendre ce script exécutable
Maintenant tu fais
Ce qu'il fait:
$*
renvoie tous les arguments sous forme de chaîne. La sortie de cette commande va par défaut à la sortie standard du script.Ainsi, la sortie standard de magicalUnionThing sera sa sortie stdin + stdout de la commande transmise en tant qu'argument.
Il existe bien sûr des moyens plus simples, comme indiqué dans les autres réponses.
Peut-être que cette alternative peut être utile dans certains cas.
la source