Ceux-ci s'appellent des opérateurs de shell et, oui, ils sont plus nombreux. Je vais donner un bref aperçu des plus courantes parmi les deux principales classes, les opérateurs de contrôle et les opérateurs de redirection , ainsi que leur fonctionnement par rapport au shell bash.
;
: Exécutera une commande après l'autre, quel que soit le résultat de la première.
command1 ; command2
Le premier command1
est exécuté, au premier plan, et une fois terminé, command2
il sera exécuté.
Une nouvelle ligne qui ne se trouve pas dans un littéral de chaîne ou après certains mots clés n'est pas équivalente à l'opérateur point-virgule. Une liste de ;
commandes simples délimitées reste une liste - comme dans l’analyseur du shell, il faut continuer à lire les commandes simples qui suivent une ;
commande simple délimitée avant de s’exécuter, alors qu’une nouvelle ligne peut délimiter toute une liste de commandes - ou liste de listes. La différence est subtile, mais compliquée: puisque le shell n’a pas d’impératif préalable pour la lecture de données suivant une nouvelle ligne, la nouvelle ligne marque un point où le shell peut commencer à évaluer les commandes simples qu’il a déjà lues, alors qu’un point ;
-virgule le fait. ne pas.
&
: Ceci lancera une commande en arrière-plan, vous permettant de continuer à travailler dans le même shell.
command1 & command2
Ici, command1
est lancé en arrière-plan et command2
commence à s'exécuter immédiatement au premier plan, sans attendre command1
de quitter.
Une nouvelle ligne après command1
est facultative.
&&
: Utilisé pour construire des listes AND, il vous permet d'exécuter une commande uniquement si une autre est sortie avec succès.
command1 && command2
Ici, command2
sera exécuté après command1
a terminé et seulement si command1
a réussi (si son code de sortie était 0). Les deux commandes sont exécutées au premier plan.
Cette commande peut aussi être écrite
if command1
then command2
else false
fi
ou simplement if command1; then command2; fi
si le statut de retour est ignoré.
||
: Utilisé pour construire des listes OR, il vous permet d'exécuter une commande uniquement si une autre a été abandonnée sans succès.
command1 || command2
Ici, command2
ne fonctionnera qu'en cas d' command1
échec (s'il a renvoyé un état de sortie autre que 0). Les deux commandes sont exécutées au premier plan.
Cette commande peut aussi être écrite
if command1
then true
else command2
fi
ou d'une manière plus courte if ! command1; then command2; fi
.
Notez que &&
et ||
sont à gauche associative; voir Priorité des opérateurs logiques du shell &&, || pour plus d'informations.
!
: Ceci est un mot réservé qui agit en tant qu'opérateur "not" (mais doit avoir un délimiteur), utilisé pour annuler le statut de retour d'une commande - renvoie 0 si la commande renvoie un statut différent de zéro, renvoie 1 si renvoie le statut 0 Aussi un NON logique pour l' test
utilitaire.
! command1
[ ! a = a ]
Et un véritable opérateur NOT dans les expressions arithmétiques:
$ echo $((!0)) $((!23))
1 0
Ceux-ci vous permettent de contrôler l'entrée et la sortie de vos commandes. Ils peuvent apparaître n'importe où dans une commande simple ou suivre une commande. Les redirections sont traitées dans l'ordre dans lequel elles apparaissent, de gauche à droite.
<
: Donne une entrée à une commande.
command < file.txt
Ce qui précède s'exécutera command
sur le contenu de file.txt
.
<>
: idem que ci-dessus, mais le fichier est ouvert en mode lecture + écriture au lieu de lecture seule :
command <> file.txt
Si le fichier n'existe pas, il sera créé.
Cet opérateur est rarement utilisé car les commandes ne lisent généralement que leur stdin, bien qu'il puisse s'avérer utile dans un certain nombre de situations spécifiques .
>
: Dirige la sortie d'une commande dans un fichier.
command > out.txt
Ce qui précède sauvera la sortie de command
as out.txt
. Si le fichier existe, son contenu sera écrasé et s'il n'existe pas, il sera créé.
Cet opérateur est également souvent utilisé pour choisir si quelque chose doit être imprimé avec une erreur standard ou une sortie standard :
command >out.txt 2>error.txt
Dans l'exemple ci-dessus, >
redirige la sortie standard et 2>
redirige l'erreur standard. La sortie peut également être redirigée à l'aide de 1>
mais, comme il s'agit de la valeur par défaut, le 1
est généralement omis et écrit simplement comme >
.
Donc, pour courir command
sur file.txt
et enregistrer sa sortie out.txt
et les messages d'erreur dans error.txt
vous courrais:
command < file.txt > out.txt 2> error.txt
>|
: Fait la même chose que >
, mais écrasera la cible, même si le shell a été configuré pour refuser l'écrasement (avec set -C
ou set -o noclobber
).
command >| out.txt
S'il out.txt
existe, la sortie de command
remplacera son contenu. S'il n'existe pas, il sera créé.
>>
: Fait la même chose que >
, sauf que si le fichier cible existe, les nouvelles données sont ajoutées.
command >> out.txt
S'il out.txt
existe, la sortie de command
y sera ajoutée après tout ce qui s'y trouve déjà. S'il n'existe pas, il sera créé.
&>
, >&
, >>&
Et &>>
: (non standard). Redirige les erreurs standard et les sorties standard, en les remplaçant ou en les ajoutant, respectivement.
command &> out.txt
L'erreur standard et la sortie standard de command
seront enregistrées dans out.txt
, en écrasant son contenu ou en le créant s'il n'existe pas.
command &>> out.txt
Comme ci-dessus, sauf que s'il out.txt
existe, la sortie et l'erreur de command
y seront ajoutées.
La &>
variante est originaire de bash
, tandis que la >&
variante provient de csh (des décennies plus tôt). Ils sont tous deux en conflit avec d'autres opérateurs shell POSIX et ne doivent pas être utilisés dans des sh
scripts portables .
<<
: Un document ici. Il est souvent utilisé pour imprimer des chaînes multilignes.
command << WORD
Text
WORD
Ici, command
tout prendra jusqu'à ce qu'il trouve l' entrée suivante de WORD
, Text
dans l'exemple ci-dessus, en tant qu'entrée. Bien que cela WORD
soit souvent le cas EoF
, il peut s'agir de n'importe quelle chaîne alphanumérique (et pas seulement) que vous aimez. Quand WORD
est cité, le texte dans le présent document est traité littéralement et aucune expansion n'est effectuée (sur des variables par exemple). Si elle n'est pas citée, les variables seront développées. Pour plus de détails, voir le manuel bash .
Si vous souhaitez diriger command << WORD ... WORD
directement la sortie vers une ou plusieurs autres commandes, vous devez placer le canal sur la même ligne que << WORD
vous ne pouvez pas le placer après le mot de fin ou sur la ligne suivante. Par exemple:
command << WORD | command2 | command3...
Text
WORD
<<<
: Voici des chaînes, similaires aux documents ici, mais destinées à une seule ligne. Celles-ci n'existent que dans le port Unix ou rc (d'où il provient), zsh, certaines implémentations de ksh, yash et bash.
command <<< WORD
Tout ce qui est donné WORD
est étendu et sa valeur est passée en entrée command
. Ceci est souvent utilisé pour passer le contenu des variables en entrée d'une commande. Par exemple:
$ foo="bar"
$ sed 's/a/A/' <<< "$foo"
bAr
# as a short-cut for the standard:
$ printf '%s\n' "$foo" | sed 's/a/A/'
bAr
# or
sed 's/a/A/' << EOF
$foo
EOF
Cela ne concerne que les opérateurs les plus courants des obus Bourne-like. Certains shells ont quelques opérateurs de redirection supplémentaires.
bash
. Ceci est considéré comme une question canonique pour clore les diverses questions "Que fait cette chose étrange?" Et la plupart d'entre elles proviennent d'utilisateurs de bash. J'espère que quelqu'un d'autre interviendra et répondra pour les obus autres que bash, mais mettre en évidence ceux spécifiques à bash a beaucoup de sens. Je devrai vérifier cependant, je ne sais pas quels sont ceux qui me viennent à l'esprit.&>
,>>>
Et<<<
sont non-POSIX est la référence à non seulement les caractères non-Alphanum dans le nom d'ici-doc. Cette réponse discute aussi très peu de choses sur la façon dont ils travaillent - par exemple, il est presque pire que inutile de parler d'une simple commande et une commande sans expliquer ce que ceux - ci et la façon dont le shell décide.false
) et un code de sortie de 0 indique un succès (nontrue
). Cela a toujours été le chemin et est assez standard. Un code de sortie non-0 indique une erreur dans tous les environnements que je connais.Avertissement concernant '>'
Les débutants Unix qui viennent d’apprendre la redirection des E / S (
<
et>
) essaient souvent des choses comme:ou
ou, presque équivalent,
(
grep
,sed
,cut
,sort
Etspell
sont des exemples de commandes que les gens sont tentés d'utiliser dans les constructions comme celles - ci.) Les utilisateurs sont surpris de découvrir que ces scénarios aboutissent dans le fichier se vider.Une nuance qui ne semble pas être mentionnée dans l'autre réponse se cache dans la première phrase de la section Redirection de bash (1) :
Les cinq premiers mots doivent être en gras, en italique, souligné, agrandi, clignotant, coloré en rouge et marqué d'une icône pour souligner le fait que le shell effectue la ou les redirection (s) demandée (s) avant l'exécution de la commande . Et rappelez-vous aussi
Donc, dans cet exemple:
le shell ouvre le
roster
fichier en écriture en le tronquant (c.-à-d. en supprimant tout son contenu) avant que lesort
programme ne commence à s'exécuter. Naturellement, rien ne peut être fait pour récupérer les données.On pourrait s'attendre naïvement à ce que
pourrait être mieux. Comme le shell gère les redirections de gauche à droite, il s'ouvre
poem
en lecture (pourtr
l'entrée standard de), avant de l'écrire en écriture (pour la sortie standard). Mais ça n'aide pas. Même si cette séquence d'opérations génère deux descripteurs de fichier, ils renvoient tous deux au même fichier. Lorsque le shell ouvre le fichier en lecture, le contenu est toujours là, mais il continue à être compressé avant l'exécution du programme.Alors, que faire à ce sujet?
Les solutions comprennent:
Vérifiez si le programme que vous exécutez dispose de sa propre capacité interne permettant de spécifier l'emplacement de la sortie. Ceci est souvent indiqué par un
-o
(ou--output=
) jeton. En particulier,est à peu près équivalent à
sauf que, dans le premier cas, le
sort
programme ouvre le fichier de sortie. Et il est assez intelligent pour ne pas ouvrir le fichier de sortie jusqu'à ce que après avoir lu tous les fichiers d'entrée (s).De même, au moins certaines versions de
sed
ont une option-i
(edit i n place) qui peut être utilisée pour écrire la sortie dans le fichier d’entrée (à nouveau, après que toutes les entrées aient été lues). Éditeurs commeed
/ex
,emacs
,pico
etvi
/vim
permettent à l'utilisateur d'éditer un fichier texte et enregistrez le texte modifié dans le fichier d' origine. Notez queed
(au moins) peut être utilisé de manière non interactive.vi
a une caractéristique connexe. Si vous tapez , le contenu du tampon d'édition sera écrit , la sortie et insérée dans le tampon (en remplacement du contenu d'origine).:%!command
Entercommand
Simple mais efficace:
Cela a pour inconvénient que, s’il
input_file
s’agit d’un lien, il sera (probablement) remplacé par un fichier séparé. En outre, le nouveau fichier appartiendra à vous, avec les protections par défaut. Cela risque en particulier de rendre le fichier lisible par tout le monde, même si le fichier originalinput_file
ne l’était pas.Variations:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
qui laissera (potentiellement) le
temp_file
monde lisible. Encore mieux:cp input_file temp_file && command … temp_file > input_file && rm temp_file
Celles-ci préservent l’état de la liaison, le propriétaire et le mode (protection) du fichier, éventuellement au prix de deux fois plus d’E / S. (Vous devrez peut - être utiliser une option comme
-a
ou-p
surcp
pour lui dire de conserver les attributs.)command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(divisé en lignes séparées uniquement pour des raisons de lisibilité) Cela préserve le mode du fichier (et, si vous êtes root, le propriétaire), mais le fait appartenir à vous (si vous n'êtes pas root), et en fait un nouveau, fichier séparé.
Ce blog (édition de fichiers «sur place») suggère et explique
Cela nécessite de
command
pouvoir traiter les entrées standard (mais presque tous les filtres le peuvent). Le blog lui-même appelle cela un kludge risqué et décourage son utilisation. Et cela créera également un nouveau fichier séparé (non lié à quoi que ce soit), appartenant à vous et avec les autorisations par défaut.Le paquet moreutils a une commande appelée
sponge
:Voir cette réponse pour plus d'informations.
Voici quelque chose qui m'a complètement surprise: syntaxerror dit :
Ce qui suit peut fonctionner dans ce cas:
sort
, outr
sans l’ option-d
ou-s
), vous pouvez essayer: Reportez - vous à cette réponse et à cette réponse pour plus d'informations, y compris une explication de ce qui précède, et des solutions de rechange qui fonctionnent si votre commande produit la même quantité de données en sortie qu'il y a de données en entrée ou moins (par exemplegrep
, oucut
). Ces réponses ont l'avantage de ne pas nécessiter d'espace libre (ou très peu). Les réponses ci-dessus du formulaire exigent clairement qu'il y ait suffisamment d'espace libre pour que le système puisse contenir simultanément tout le fichier d'entrée (ancien) et le fichier de sortie (nouveau); Ceci est également vrai pour la plupart des autres solutions (par exemple, et ). Exception: nécessitera probablement beaucoup d'espace libre, carcommand … input_file > temp_file && …
sed -i
sponge
sort … | dd …
sort
a besoin de lire toutes ses entrées avant de pouvoir écrire une sortie, et il stocke probablement en mémoire tampon la plupart sinon la totalité de ces données dans un fichier temporaire.dd
réponse ci-dessus. La syntaxe ouvre le fichier nommé sur le descripteur de fichier pour les entrées et les sorties , sans le tronquer - une sorte de combinaison de et . Remarque: Certains programmes (par exemple, et ) peuvent refuser de s'exécuter dans ce scénario car ils peuvent détecter que l'entrée et la sortie sont le même fichier. Reportez - vous à cette réponse pour en savoir plus sur ce qui précède, ainsi qu’à un script qui permet à cette réponse de fonctionner s’il est garanti que votre commande produira la même quantité de données en sortie qu’il ya une entrée ou moins . Attention: je n'ai pas testé le script de Peter, je ne le garantis donc pas.n<> file
n
n<
n>
cat
grep
Alors, quelle était la question?
Cela a été un sujet populaire sur U & L; il est abordé dans les questions suivantes:
iconv
remplacer le fichier d'entrée par la sortie convertie?shuf file > file
laisse-t-elle un fichier vide?sort
commande me donne-t-elle un fichier vide?tr
stdout vers un fichier… Et cela ne compte pas Super User ou Ask Ubuntu. J'ai incorporé beaucoup d'informations des réponses aux questions ci-dessus dans cette réponse, mais pas toutes. (Par exemple, pour plus d'informations, lisez les questions ci-dessus et leurs réponses.)
PS Je n'ai aucune affiliation avec le blog que j'ai cité ci-dessus.
la source
/tmp
.dash
serait la coquille de récupération par défaut sur Ubuntu et non seulement pas comprendre un<<<
herestring, mais il obtient également des tuyaux anonymes pour<<
heredocuments et ne plaisante pas avec${TMPDIR:-/tmp}
pour cela but du tout. Voir ceci ou cela pour des démonstrations sur la gestion des documents ici. Aussi, pourquoi la même quantité de sortie ou moins d' avertissement?dd … conv=notrunc
et les1<>
réponses ne tronquer le fichier de sortie, de sorte que , si la sortie de la commande est inférieure à l'entrée (par exemplegrep
), il y aura quelques octets de l'original reste à la fin du fichier. Et, si la sortie est plus grande que l'entrée (par exemplecat -n
,nl
ou (potentiellement)grep -n
), il y a un risque d'écraser les anciennes données avant de l' avoir lu.Plus d' observations sur
;
,&
,(
et)
Notez que certaines des commandes de la réponse de terdon peuvent être nulles. Par exemple, vous pouvez dire
(avec non
command2
). Ceci est équivalent à(c’est-à-dire qu’il passe tout simplement
command1
au premier plan et attend son achèvement. De manière comparable,(avec non
command2
) se lanceracommand1
en arrière-plan, puis émettra immédiatement une autre invite du shell.En revanche,
command1 &&
,command1 ||
etcommand1 |
ne font pas de sens. Si vous en tapez un, le shell supposera (probablement) que la commande est continuée sur une autre ligne. Il affichera l'invite du shell secondaire (continuation), qui est normalement défini sur>
, et continue à lire. Dans un script shell, il va simplement lire la ligne suivante et l'ajouter à ce qu'il a déjà lu. (Attention: ce n'est peut-être pas ce que vous voulez.)Remarque: certaines versions de certains shells peuvent traiter des commandes incomplètes comme des erreurs. Dans de tels cas (ou dans les cas où vous avez une longue commande), vous pouvez mettre une barre oblique inverse (
\
) à la fin d'une ligne pour indiquer au shell de continuer à lire la commande sur une autre ligne:ou
Comme dit terdon,
(
et)
peut être utilisé pour regrouper des commandes. La déclaration selon laquelle ils ne sont «pas vraiment pertinents» dans cette discussion est discutable. Certaines des commandes dans la réponse de terdon peuvent être des groupes de commandes . Par exemple,est ce que ca:
command1
et attendez que ça finisse.command2
et attendez la fin.Ensuite, si
command2
réussi,command3
et attendez que ça finisse.command4
et attendez la fin de l'opération.En cas d'
command2
échec, arrêtez de traiter la ligne de commande.En dehors des parenthèses,
|
lie très étroitement, doncest équivalent à
et
&&
et||
lier plus serré que;
, doncest équivalent à
c'est-à-dire,
command3
sera exécuté quel que soit le statut de sortie decommand1
et / oucommand2
.la source
;
une erreur de syntaxe, et non une commande vide, est une erreur de syntaxe et non une instruction vide. C'est donc; ;
une erreur. (Un piège commun pour les nouveaux utilisateurs, IMHO). Aussi:;;
est un délimiteur spécial, pour lescase
déclarations.;
,&&
,||
,&
et|
, sont des erreurs si elles apparaissent avec rien qui les précède. En outre, terdon a répondu;;
(brièvement) dans sa réponse.linebreak
jeton dans la grammaire du shell POSIX. Donc, il est peut-être prudent de dire que tous les shells compatibles POSIX les accepteront. Je maintiens ma déclaration comme un disclaimer général; Si vous trouvez un shell suffisamment ancien, tel qu'un shell Bourne ou plus ancien, tous les paris sont ouverts.