Comment fonctionnent `>` et `>>`?

9

J'ai essayé revun fichier, puis je l'ai redirigé, cat > same_filemais il se transformait en un fichier vierge.

Pendant que j'essayais, rev file.txt | cat > file2.txt && mv file.txt file2.txt;ça fonctionnait.

Même rev file.txt | cat >> file.txt;travaillé.

Mais quand j'ai essayé, rev file.txt | cat > file.txtça a échoué.

Vintux
la source
Vous pouvez également laisser catcomme ça: rev file.txt > file2.txt && mv file2.txt file.txt. C'est une utilisation superflue decat . En le laissant de côté, vous épargnez de générer un processus supplémentaire.
matega

Réponses:

19

La chose fondamentale que vous devez saisir dans ce cas entre les deux façons de rediriger (> et >>) est:

>

Redirige et remplace les informations vers lesquelles elles ont été dirigées. Cela se produit lors de la réception d'informations via le canal "|"

>>

Redirige et concatène les informations vers lesquelles il a été signalé. Cela se produit lors de la réception d'informations via le canal "|"

Dans les deux cas, si le fichier n'existe pas, il sera créé à la place. Ce n'est que sur ">>" que les informations seront concaténées si vous les réexécutez sur le même fichier. Avec ">", vous écraseriez simplement tout ce que vous avez fait lors de la première exécution.

Mais voici l'affaire lorsque vous utilisez le même fichier d'entrée que le fichier de sortie. Dans ce cas particulier, si vous utilisez ">", vous supprimez les informations que la partie "entrée" doit analyser, car le fichier de sortie "l'écrase". Donc dans:

rev file.txt | cat > file.txt

Ce qui se passe réellement dans "l'explication au ralenti" est:

  1. revse prépare à inverser le contenu de file.txtet à l'envoyer au tuyau
  2. Pendant l' revenvoi des informations au canal, le canal les transmet directement cat.
  3. Pendant la catréception des informations, il les appliquera automatiquement à celles avec lesquelles file.txtelles ont été définies.
  4. Le mot-clé ici est "pendant", car tout se passe en même temps. Veuillez voir les excellents commentaires ci-dessous d'Emil pour avoir une compréhension plus profonde de cette partie.
  5. catn'attendra pas pour revdiriger le fichier entier. Il démarre simplement à la minute où la première partie des informations y parvient, ce qui signifie que, selon le symbole que vous avez utilisé, il ouvrira une connexion file.txt.
  6. Dans ce cas, puisque vous avez utilisé le > au lieu de >> , le shell tronquera le fichier de sortie, ce qui signifie qu'il ouvrira et effacera les informations file.txten attendant que les nouvelles informations y parviennent. Avec >>, il ouvrirait une connexion avec file.txtet attendrait de nouvelles informations sur la dernière ligne détectée.
  7. Étant donné que les informations ont déjà été effacées file.txtavec > , revj'essaierais de faire son travail et n'obtiendrais rien car cattout a été supprimé en préparation des nouvelles informations.

Alors pourquoi les autres fonctionnent après avoir lu ce qui précède. À cause de ce:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

Ici, vous dirigez vers cat qui envoie les informations vers un autre fichier. Dans ce cas, le fichier d'entrée traité file.txtn'est pas le même que le fichier de sortie file2.txt. Après cela, vous écrasez littéralement le tout file2.txtavec file.txt, donc tout le processus effectué par a catété supprimé. Fondamentalement, la ligne entière pourrait être simplifiée, cp file.txt file2.txtcar elle fait la même chose puisqu'à file2.txtla fin perd la revet est écrasée par la mvcommande.

rev file.txt | cat >> file.txt

Dans ce cas, vous concaténez les informations dans le même fichier. Il ouvre donc uniquement une connexion à ce fichier mais n'efface pas les informations comme vu avec un seul > . Le résultat final doit être, les informations d'origine plus les informations inversées.

Luis Alvarado
la source
5
Le fichier n'est pas tronqué par cat. Il est tronqué par le shell, avant même que l' une des commandes du pipeline ne soit lancée.
Emil Jeřábek
Correct, cherchait des mots plus faciles à expliquer. Puisqu'il est un peu difficile d'expliquer si l'OP ne sait pas ce qu'est un shell et tout ça. Essayer de le rendre aussi "amical" que possible.
Luis Alvarado
1
Eh bien, peu importe que cela soit fait par le shell, mais que le timing que vous présentez soit incorrect. La troncature ne se produira pas à l'étape 6, mais à l'étape 0. rev file.txt | cat --bogus-option > file.txttronquera également le fichier, même si cat ne tentera pas de l'ouvrir.
Emil Jeřábek
@ EmilJeřábek vous avez raison. Les utilisateurs qui ne savent pas comment il se comportera auront plus de facilité si nous allons pas à pas avec uniquement les commandes. De plus, votre exemple envoie toujours les informations dans le même fichier, donc bash lira toute cette ligne, verra la sortie et l'ouvrira toujours ET la tronquera. L'erreur est simplement la sortie de stderr vers stdout.
Luis Alvarado
4
Voir aussi moreutils , une fantastique collection d'outils (disponible à partir du référentiel de packages en tant que moreutils) qui comprend sponge, un outil spécialement conçu pour l'utilisation de l'écrasement d'un fichier d'entrée. Par exemple, la rev file.txt >file2.txt && mv file2.txt file.txtsolution de contournement deviendrait rev file.txt | sponge file.txt, ce qui fonctionnerait correctement même s'il y a déjà quelque chose nommé file2.txt.
Daniel Wagner
9

Lorsque le shell voit la redirection, il ouvre d'abord les fichiers pertinents, avant d'exécuter l'une des commandes impliquées. Ainsi, lorsque vous faites:

foo file.txt | bar > file.txt

La redirection vers le file.txtfait tronquer avant de foo s'exécuter et peut être lu file.txt. En passant, c'est pourquoi vous ne pouvez pas faire:

sed 'blah' file.txt > file.txt

Et pourquoi seda une option d'édition sur place.

Enfin, faire:

.. | cat > file.txt

est une utilisation inutile du chat , surtout si vous essayez de lire file.txtplus tôt.

Si vous souhaitez inverser un fichier sur place, il n'y a pas de raccourcis . Vous pourrez peut-être utiliser les astuces sedou awkavec la modification sur place.

muru
la source
3

>est un redirecteur (opérateur) envoyant la sortie vers autre chose
(entrée de la commande suivante, imprimante ..)

Dans votre cas, la sortie va dans un fichier file.txt, si ce fichier existe déjà, il est écrasé, sinon il est créé.

>>est un opérateur d'ajout, s'il file.txtexiste déjà, la sortie est ajoutée à la fin du fichier. si le fichier n'existe pas, il est créé et la sortie écrite dans le nouveau fichier, identique à >(redirecteur).

Ken Mollerup
la source
Le PO semble avoir compris cela. La confusion semble provenir uniquement du fait que le même fichier se trouve des deux côtés des opérateurs >et >>.
bzlm
0

Vous pouvez utiliser Vim en mode Ex:

ex -sc '%!rev' -cx file.txt
  1. % sélectionner toutes les lignes

  2. ! exécuter la commande

  3. x sauver et fermer

Steven Penny
la source