Commande Pipe couplée avec la commande cat

bonjour,

voyant très souvent cette commande j’ai voulu en savoir un peu plus . Basiquement c’est assez simple sauf que je bute sur un exmple précis qui me bloque :

mm@Xfce:~$ rm . .. 2>t.txt | cat t.txt

pourtant t.txt n’est pas vide puisque

mm@Xfce:~$ cat t.txt
rm: impossible de supprimer '.': est un dossier
rm: impossible de supprimer '..': est un dossier

par contre dans l’exemple ci-dessous la sortie est correcte

mm@Xfce:~$ printf %b  'hello V.G' "\n"  'hello  D.S' "\n" > t.txt | cat t.txt 
hello V.G
hello  D.S

question : pourquoi la ligne

rm . .. 2>t.txt | cat t.txt

qui devrait afficher le texte contenu dans t.txt ne fonctionne pas alors que

mm@Xfce:~$ printf %b  'hello V.G' "\n"  'hello  D.S' "\n" > t.txt | cat t.txt

affiche bien le contenu du fichier t.txt ?

La partie rm qu’on a pas en entier envoie les éventuels retours d’affichage dans le fichier t.txt.
Le cat affichant le contenu.
en fait c’est inélégant, car inutile, les affichages provoqués par rm sont directement visible, donc pas besoin de les envoyer dans un fichier pour immédiatement l’afficher.

je ne sais pas où tu as trouvé ça, mais ça ne se fait pas vraiment.

les 2 lignes de commande sont faites maison , pas étonnant que ça pique pour un professionnel . Leur unique but : essayer les 2 commandes | et cat avec en plus la sortie du fichier stderr que je viens de découvrir , alors je me suis servi de la 1ère commande récente qui m’a sorti une erreur et qui m’est venue à l’esprit .

et ce que j’ai trouvé bizarre c’est que si je redirige la sortie de stdout ça fonctionne :

mm@Xfce:~$ rm . .. 1> t.txt | cat t.txt
rm: impossible de supprimer '.': est un dossier
rm: impossible de supprimer '..': est un dossier

mais bon c’est juste par curiosité , je ne vais pas me focaliser là-dessus .

merci pour la réponse .

Essaye plutot un truc du genre:

ip -o link show | grep -v '1\: lo\:' | cut -d ':' -f2 | sed "s/\s//g"

Qui te donnera les interfaces aures que lo sans espaces à la fin ou au début. :wink:

Ça dépends de ce que tu veux dire par : ça fonctionne

rm . .. 1> t.txt | cat t.txt

Dans le cas de la ligne de commandes ci-dessus, comme le message d’erreur retourné dans le flux stderr par la commande rm n’est plus redirigé, il s’affiche dans la console.

Mais le fichier t.txt sera vidé de ce qu’il contenait (s’il contenait déjà autre chose)
puisque le flux stdout de la commande rm n’aura rien retourné.

awk peut avantageusement remplacer les combinaisons de grep et cut:

ip -o link | awk -F": " '!/lo/ {print $2}'

devrait donner à peu près la même chose

pour être sûr je vais supprimer le fichier avant de réessayer :

mm@Xfce:~$ rm t.txt
mm@Xfce:~$ rm . .. 1> t1.txt | cat t1.txt
rm: impossible de supprimer '.': est un dossier
rm: impossible de supprimer '..': est un dossier

Ton fichier t1.txt est bien vide, comme l’a écrit MicP, mais cat concatène ce fichier (vide) avec l’erreur standard de la commande rm

michel@deb114x:~$ echo "contenu de t1.txt" > t1.txt
michel@deb114x:~$ echo "contenu de t2.txt" > t2.txt
michel@deb114x:~$ cat t1.txt t2.txt
contenu de t1.txt
contenu de t2.txt
michel@deb114x:~$ rm -v . .. 1> t1.txt | cat t2.txt
contenu de t2.txt
rm: impossible de supprimer '.': est un dossier
rm: impossible de supprimer '..': est un dossier
michel@deb114x:~$ cat t1.txt
michel@deb114x:~$ cat t2.txt
contenu de t2.txt
michel@deb114x:~$ 

ok , voilà l’explication = concaténation . 1&2 en somme . J’ai vu passer un truc comme ça dans une page sur ces fichiers virtuels . Je n’avais pas du tout compris la 1ère réponse de @MicP .

merci bien pour la réponse .

Tout à fait.
Le contenu de t1.txt est écrasé par la sortie standard (vide) de la commande rm. Et cat concatène ensuite t2 avec l’erreur standard de la commande rm

je viens enfin de comprendre cette réserve .

merci pour ces explications .

du manuel à propos de la commande cat :

DESCRIPTION
Concaténer le ou les FICHIER(s) sur la sortie standard.

   L'entrée  standard  est  lue  quand  FICHIER est omis ou quand FICHIER vaut
   « - ».

que signifie le tiret (?) « - » dans ce contexte ?

Il me semble que ton problème vient (entre autres) de l’utilisation du pipe avec les redirections. Ce qui n’a pas l’air trivial à part pour stdout.
Tu peux lire cette page, c’est intéressant (et pas simple).
Il y est dit que :

Le stdin du côté droit du pipe ‹ | › prend toujours sa source du stdout du côté gauche

Et donc si je comprends bien, quand tu tapes :

rm . .. 2>t.txt | cat t.txt

Il n’y a rien dans le stdout du côté gauche, et donc le pipe ne peut fonctionner. De plus, si tu cherches à enchaîner deux commandes, ce n’est pas un pipe (|) qu’il faut utiliser, mais un point-virgule (:wink: :

rm . .. 2>t.txt ; cat t.txt

Et là ça fonctionne.

1 J'aime

effectivement ça n’a pas l’air évident évident et je vais laisser ça de côté car de toute façon ces fichiers virtuels ne me sont pas du tout indispensables : je connais leur existence et ça suffira .

en conclusion : pour tester ces deux commandes c’était l’exemple à ne surtout pas choisir . pff…
merci pour l’info .

Dans ce contexte, le tiret représente l’entrée standard :

michel@deb114x:~$ echo "contenu de t1.txt" > t1.txt
michel@deb114x:~$ echo "t2.txt vers stdin de la commande qui sera après le pipe => sera remplacé par le tiret" > t2.txt
michel@deb114x:~$ cat t1.txt
contenu de t1.txt
michel@deb114x:~$ cat t2.txt
t2.txt vers stdin de la commande qui sera après le pipe => sera remplacé par le tiret
michel@deb114x:~$ #############################################
michel@deb114x:~$ 
michel@deb114x:~$ cat t2.txt | cat t1.txt
contenu de t1.txt
michel@deb114x:~$ 
michel@deb114x:~$ cat t2.txt | cat
t2.txt vers stdin de la commande qui sera après le pipe => sera remplacé par le tiret
michel@deb114x:~$ 
michel@deb114x:~$ #############################################
michel@deb114x:~$ cat t2.txt | cat - t1.txt
t2.txt vers stdin de la commande qui sera après le pipe => sera remplacé par le tiret
contenu de t1.txt
michel@deb114x:~$ 
michel@deb114x:~$ cat t2.txt | cat t1.txt -
contenu de t1.txt
t2.txt vers stdin de la commande qui sera après le pipe => sera remplacé par le tiret
michel@deb114x:~$ 

cat ne concatène rien du tout. Comme l’a écrit @Micp, il affiche le contenu du fichier passé en argument. L’affichage des messages d’erreurs est dû à la sortie d’erreur de rm qui n’est pas redirigée.

J’ajoute que, dans la ligne de commandes suivante :

rm . .. 2>t.txt | cat t.txt

le pipe connecte :

  • le flux stdout de la commande rm
  • au flux stdin de la commande cat

Le pipe ne prends pas en compte le flux stderr de la commande rm

Mais, dans ce contexte ( …impossible de supprimer …) :

  • La commande rm ne retourne rien du tout par son flux stdout => donc la commande pipe n’aura rien à transmettre au flux stdin de la commande cat
  • de plus, pour que la commande cat lise son flux stdin il faudrait qu’on ne lui ait donné aucun nom de fichier, ou bien qu’on lui spécifie de lire aussi son flux stdin en ajoutant un tiret dans la liste des noms de fichiers à concaténer.
1 J'aime

même si je ne comprends pas pourquoi la transmission des flux se passe ainsi , ça explique le résultat observé . Trop de trous dans la raquette pour que je sois capable de suivre le chemin emprunté par les flux de données . Sans le savoir j"ai visé trop haut .

Mais en séparant les flux je vois mieux ce qu’il se passe , transmissions avec pipe non comprises :

mm@Xfce:~$ rm . .. 1>t1.txt 2>t2.txt
mm@Xfce:~$ cat t1.txt
mm@Xfce:~$ cat t2.txt
rm: impossible de supprimer '.': est un dossier
rm: impossible de supprimer '..': est un dossier

Bonjour

Une page web (récemment mise à jour par l’auteur) très bien faite
concernant les redirections et le pipe :
Introduction à la programmation en Bash → #5 Redirections élémentaires


Et c’est même le document en entier qui vaut le coup d’être lu :
iut-rodez.fr : Introduction à la programmation en Bash (Eric Sanchis)
et si besoin, tu trouveras dans ces pages web un lien vers un fichier pdf

Je pense que c’est plutot
rm quelquechose 2> /tmp/glop || cat /tmp/glop
qui efface le qquelkquechose et affiche les erreurs si il y en a eu tout en les conservant dans un fichier.