Bonjour, Je suis devant un comportement de joe dans un while que je ne comprend pas. J'ai une liste de fichiers à éditer pour contrôle et modifs éventuelles, j'ai donc lancé un while read f; do joe $f; done < fichiers.list mais - si fichiers.list commence par une ligne vide, ça m'ouvre joe avec un nouveau fichier qui contient le contenu de fichiers.list (comme si joe recevait $f sur son entrée standard et pas comme argument), - sinon, ça ouvre le premier fichier en y ajoutant à la fin la suite de fichiers.list (les noms des fichiers de la liste, pas leur contenu) alors que while read f; do echo $f|xargs joe; done < fichiers.list ou bien for f in $(cat fichiers.list); do joe $f;done; ont bien l'effet escompté (ouvre le premier fichier de la liste et passe au suivant à chaque fermeture de fichier). J'ai aussi testé avec nano, mais seule la solution avec le for fonctionne, les autres donnent du "Received SIGHUP or SIGTERM" Une explication ? -- Daniel PS: pour ceux qui veulent tester # le contenu de test mkdir tmp cd tmp echo -e "tata\nbla\nblabla" >tata echo -e "titi\nbli\nblibli" >titi echo -e "toto\nblo\nbloblo" >toto echo -e "tata\ntiti\ntoto">fichiers.list echo >liste2 # et les tests while read f; do joe $f; done < fichiers.list while read f; do echo $f|xargs joe; done < fichiers.list for f in $(cat fichiers.list); do joe $f;done; while read f; do joe $f; done < liste2 while read f; do nano $f; done < fichiers.list while read f; do echo $f|xargs nano; done < fichiers.list for f in $(cat fichiers.list); do nano $f;done;
On 2007-08-07 11:21:01 +0200, Daniel Caillibaud wrote:
J'ai aussi testé avec nano, mais seule la solution avec le for fonctionne, les autres donnent du "Received SIGHUP or SIGTERM"
Une explication ?
C'est peut-être parce que le processus n'a pas un stdin attaché au terminal ou un truc du genre, auquel cas le comportement peut varier d'un éditeur à un autre. -- Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/> 100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/> Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
Vincent Lefevre a écrit :
C'est peut-être parce que le processus n'a pas un stdin attaché au terminal ou un truc du genre, auquel cas le comportement peut varier d'un éditeur à un autre.
Oui, mais je comprend pas trop pourquoi ça réagit différemment entre while read f; do #commandes#; done<fichier et for f in `cat fichier`; do #commandes#; done; -- Daniel
On 2007-08-07 17:13:01 +0200, Daniel Caillibaud wrote:
Vincent Lefevre a écrit :
C'est peut-être parce que le processus n'a pas un stdin attaché au terminal ou un truc du genre, auquel cas le comportement peut varier d'un éditeur à un autre.
Oui, mais je comprend pas trop pourquoi ça réagit différemment entre
while read f; do #commandes#; done<fichier et for f in `cat fichier`; do #commandes#; done;
Comme je l'ai dit, il peut y avoir un problème quand le processus n'a pas un stdin attaché au terminal (ce qui se produit avec la première ligne). Par exemple: vin% cat file foo.c vin% while read f; do emacs -nw $f; done < file emacs: standard input is not a tty vin% Essaie plutôt un truc du style: while read f; do emacs -nw $f < $TTY; done < file ou while read f <&3; do emacs -nw $f; done 3< file -- Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/> 100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/> Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
Vincent Lefevre a écrit :
On 2007-08-07 17:13:01 +0200, Daniel Caillibaud wrote:
Vincent Lefevre a écrit :
C'est peut-être parce que le processus n'a pas un stdin attaché au terminal ou un truc du genre, auquel cas le comportement peut varier d'un éditeur à un autre. Oui, mais je comprend pas trop pourquoi ça réagit différemment entre
while read f; do #commandes#; done<fichier et for f in `cat fichier`; do #commandes#; done;
Comme je l'ai dit, il peut y avoir un problème quand le processus n'a pas un stdin attaché au terminal (ce qui se produit avec la première ligne). Par exemple:
Mais pourquoi le for "propage" le stdin vers les commandes de la boucle et pas le while ? Ce sont deux "shell keyword"... je comprend pas pourquoi ça réagit différemment.
vin% cat file foo.c vin% while read f; do emacs -nw $f; done < file emacs: standard input is not a tty vin%
Essaie plutôt un truc du style:
while read f; do emacs -nw $f < $TTY; done < file
$ while read f; do joe $f <$TTY ; done <fichiers.list -bash: $TTY: ambiguous redirect -bash: $TTY: ambiguous redirect ..
ou
while read f <&3; do emacs -nw $f; done 3< file
while read f<&3; do joe $f; done 3<fichiers.list marche comme attendu (idem for). Merci Vincent, j'aurai pas trouvé ça tout seul ;-) -- Daniel
On 2007-08-07 18:58:02 +0200, Daniel Caillibaud wrote:
Vincent Lefevre a écrit :
On 2007-08-07 17:13:01 +0200, Daniel Caillibaud wrote:
while read f; do #commandes#; done<fichier et for f in `cat fichier`; do #commandes#; done;
Comme je l'ai dit, il peut y avoir un problème quand le processus n'a pas un stdin attaché au terminal (ce qui se produit avec la première ligne). Par exemple:
Mais pourquoi le for "propage" le stdin vers les commandes de la boucle et pas le while ?
Le while le propage[*] aussi, mais le stdin du while, c'est le fichier "fichier", pas le stdin par défaut (i.e. le terminal) comme dans le for. D'où les deux solutions que j'ai proposées: 1. Redonner le stdin initial à l'éditeur. 2. Ne pas utiliser le descripteur de fichier 0 (stdin) pour transmettre les données au read. Normalement, le descripteur 3 est inutilisé. Donc je fais globalement passer les données dedans et je redirige vers le stdin de read. Note: si ça se trouve dans le script, le stdin pourrait aussi être redirigé lors de l'appel du script. Fournir le tty à l'éditeur est probablement la meilleure solution. [*] En fait, lors du fork, le descripteur de fichier réfère le même fichier, ce n'est pas vraiment une propagation.
Essaie plutôt un truc du style:
while read f; do emacs -nw $f < $TTY; done < file
$ while read f; do joe $f <$TTY ; done <fichiers.list -bash: $TTY: ambiguous redirect -bash: $TTY: ambiguous redirect ..
Ah, TTY est propre à zsh. Mais ceci devrait fonctionner partout: while read f; do joe $f < `tty` ; done <fichiers.list si ça tourne bien dans un terminal. Mais il vaut probablement mieux tester, et pendant qu'on y est, mettre des quotes: tty="`tty`" || tty=/dev/null while read f; do joe "$f" < "$tty" ; done <fichiers.list -- Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/> 100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/> Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)
participants (2)
-
Daniel Caillibaud
-
Vincent Lefevre