|
|
|
|
||||||
| fr.comp.os.unix Système UNIX. |
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonjour. J'ai le besoin suivant : je dois parcourir tous les fichiers présents dans une arborescence, vérifier si chacun de ces fichiers contient ou non une certaine ligne et la supprimer si c'est le cas. Quelles sont vos remarques sur le scrip que je propose ? ========================================== #!/bin/sh tar czvf faq.tgz faq/ REP=`ls -1R faq` for FICHIER in $REP do sed -e '/^X-No-Productlink:'/d $FICHIER > $FICHIER done ========================================== bonus track (mais je suis prêt à chercher) : comment faire pour virer de la liste les fichiers dont le nom se termine par ".old" ? je suppose que je dois passer par les expressions régulières, et (éventuellement ?) par find. Par avance, merci pour vos éclaircissements et liens pertinents. |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Christophe Raverdy <adresse@fai.tld.invalid> écrit :
> Bonjour. 'lu > tar czvf faq.tgz faq/ > REP=`ls -1R faq` > for FICHIER in $REP for i in $REP/**/ ; me parait être un poil mieux que de forker le ls, si le shell le permet. Sinon, un find : find $REP -type f -exec sed... ';' > sed -e '/^X-No-Productlink:'/d $FICHIER > $FICHIER Tu ne peux pas faire ça. Il y a une chance sur deux que le shell écrase le fichier $FICHIER avant que sed ne l'ouvre. Donc sed ne verra qu'un fichier vide. Le mieux est d'utiliser l'option -i (inplace) de sed pour éviter ce problème. > bonus track (mais je suis prêt à chercher) : comment faire pour virer de > la liste les fichiers dont le nom se termine par ".old" ? je suppose que > je dois passer par les expressions régulières, et (éventuellement ?) > par find. Au lieu de lancer le sed, tu fais qqchose du genre (c'est pas du code, c'est de l'algo, j'ai la flemme de faire du vrai code) : if (nom != '*.old) sed fi Si tu utilises find, tu peux faire (pas testé) : find $REP -type f -not -name '*.old' -exec sed... ';' > Par avance, merci pour vos éclaircissements et liens pertinents. Ah mais de rien, HTH |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Le 05-02-2007, Stephane Dupille a écrit:
> Christophe Raverdy <adresse@fai.tld.invalid> écrit : >> Bonjour. > > 'lu bonjour, >> tar czvf faq.tgz faq/ >> REP=`ls -1R faq` Comme tar peut prendre un certain temps, le ls peut être un peu différent ; sa sortie est polluée par des lignes vides, suivie des noms de sous-répertoires suivis de «:». On pourrait la purger avec un sed '1d;/./!{N;d}' mais ces sous-répertoires apparaissent aussi au-dessus, dans la liste de leur parent... >> for FICHIER in $REP > > for i in $REP/**/ ; > me parait être un poil mieux que de forker le ls, si le shell le > permet. Sinon, un find : > > find $REP -type f -exec sed... ';' [...] Tar fournit déjà la liste des fichiers à traiter, donc for FICHIER in $(tar cvzf temp.tgz .tmp|grep -vE '\.old$|/$') do sed -i -e '/^X-No-Productlink:/d' "$FICHIER" done pourrait suffire, du moins s'il n'y a pas de saut de ligne dans les noms de fichiers, et autres fourberies. Sinon, find ... -print0 | xargs -0 sed -i -e 'commande' <pas de fichier> >> Par avance, merci pour vos éclaircissements et liens pertinents. > > Ah mais de rien, HTH ++ -- Jacques L'helgoualc'h |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
Christophe Raverdy :
> REP=`ls -1R faq` > for FICHIER in $REP <insérer ici la rengaine sur les caractères à la con dans les noms de fichiers, j'ai la flemme de la resortir, ça passe pratiquement tous les jours sur ce NG, regarder du côté de find pour quelque chose de plus robuste.> > sed -e '/^X-No-Productlink:'/d $FICHIER > $FICHIER Là, tu vas flinguer tous tes fichiers, car le shell ouvre $FICHIER en écriture, et le tronque, avant de lancer sed... Il faut faire quelque chose comme sed ... > $FICHIER.new mv $FICHIER.new $FICHIER (perso, je ferais ça en deux passes: création des .new, vérification que c'est bon, puis une passe de renommage) ou, en plus acrobatique: (for fichier in $REP; do exec < "$fichier" rm "$fichier" sed -e ... > "$fichier" done) (explication: tu ouvres le fichier en lecture, puis tu l'effaces, mais tu gardes le fd 0 ouvert dessus, donc le fichier existe toujours, puis tu recrées un fichier vide de même nom, et enfin tu lances sed, qui va donc lire sur l'ancien fichier et écrire sur le nouveau.) À noter: la version GNU de sed a une option «-i» pour simplifier ça. > bonus track (mais je suis prêt à chercher) : comment faire pour virer de > la liste les fichiers dont le nom se termine par ".old" ? find . -name '*.old' -exec rm -- '{}' + |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Stephane Dupille :
> Il y a une chance sur deux que le shell écrase le fichier $FICHIER avant > que sed ne l'ouvre. Et même une chance sur une. |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
B'jour, Ce cher Jacques L'helgoualc'h <lhh+no_spam@free.fr> a dit : > Le 05-02-2007, Stephane Dupille a écrit: >> Christophe Raverdy <adresse@fai.tld.invalid> écrit : > >>> tar czvf faq.tgz faq/ >>> REP=`ls -1R faq` > > Comme tar peut prendre un certain temps, le ls peut être un peu > différent ; sa sortie est polluée par des lignes vides, suivie des noms > de sous-répertoires suivis de «:». On pourrait la purger avec un En plus, utiliser ls pour obtenir une liste de fichiers, c'est MAL. ls sert a formater une liste de fichiers de facon "human-friendly", mais absolument pas de facon "machine-friendly". Il y a plein d'autres methodes beaucoup plus sures, en passant par les wildcards du shell ou par find. >>> for FICHIER in $REP >> >> for i in $REP/**/ ; >> me parait être un poil mieux que de forker le ls, si le shell le >> permet. toutafait. >> Sinon, un find : >> >> find $REP -type f -exec sed... ';' > > Tar fournit déjà la liste des fichiers à traiter, donc > > for FICHIER in $(tar cvzf temp.tgz .tmp|grep -vE '\.old$|/$') > do > sed -i -e '/^X-No-Productlink:/d' "$FICHIER" > done Je propose aussi cela : tar cvzf faq.tgz faq | grep -vE '\.old$|/$' | xargs -l1 sed -i -e '/^X-No-Productlink:/d' Sauf qu'il faut gicler les noms de dossiers dans le resultat de tar, et ce n'est pas forcement evident, donc ca demande un peu de boulot en plus. Toujours garder un truc a l'esprit avec unix : FAIRE SIMPLE ET FACILE. ![]() Mais par contre, big problem, ca ne va pas rediriger le resultat dans un fichier mais dans le terminal. Et la ca devient un peu plus complique, du coup. > Pourrait suffire, du moins s'il n'y a pas de saut de ligne dans les noms > de fichiers, et autres fourberies. Sinon, > > find ... -print0 | xargs -0 sed -i -e 'commande' <pas de fichier> Ou encore find ... -exec sed -i -e "s/truc/blabla/" '{}' ';' et pour ignorer les *.old : find ./faq -type f -name "*.old" -prune -o -type f -exec sed ..... '{}' ';' Mais comme il y a la redirection a faire, je ferais plutot ceci : for i in $(find ./faq -type f -name "*.old" -prune -o -type f) do sed blablablablabla $i > $i.new done puis apres verification du resultat : for i in **/*.new do mv $i ${i/.new$/} done et basta ![]() La, c'est tout de suite mieux, non ? -- Hugues - Debianiste avant tout - http://www.hiegel.fr/~hugues/Linux/ |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Le 06-02-2007, Hugues <hugues@contact.me> a écrit:
> > B'jour, 'lut. > Ce cher Jacques L'helgoualc'h <lhh+no_spam@free.fr> a dit : >> Le 05-02-2007, Stephane Dupille a écrit: >>> Christophe Raverdy <adresse@fai.tld.invalid> écrit : >> >>>> tar czvf faq.tgz faq/ >>>> REP=`ls -1R faq` >> >> Comme tar peut prendre un certain temps, le ls peut être un peu >> différent ; sa sortie est polluée par des lignes vides, suivie des noms >> de sous-répertoires suivis de «:». On pourrait la purger avec un > > En plus, utiliser ls pour obtenir une liste de fichiers, c'est MAL. ls sert a > formater une liste de fichiers de facon "human-friendly", mais absolument pas > de facon "machine-friendly". Bon, de toutes façons c'est carrément faux : les noms de fichiers ne sont pas préfixés par leur chemin (GNU ls). Par contre, les options -p ou -F permettent de filtrer les sous-répertoires, et il y a aussi --ignore='*.old" qui peut servir. [...] >> Tar fournit déjà la liste des fichiers à traiter, donc >> >> for FICHIER in $(tar cvzf temp.tgz .tmp|grep -vE '\.old$|/$') >> do >> sed -i -e '/^X-No-Productlink:/d' "$FICHIER" >> done > > Je propose aussi cela : > > tar cvzf faq.tgz faq | grep -vE '\.old$|/$' | xargs -l1 sed -i -e '/^X-No-Productlink:/d' pas besoin du -l1, sed -i -e commandes traitera plusieurs fichiers à la fois. > Sauf qu'il faut gicler les noms de dossiers dans le resultat de tar, > et ce n'est pas forcement evident, donc ca demande un peu de boulot en > plus. mais non, c'est ce qu'a fait le «grep -v '$/'» --- tar ne répète pas les noms de sous-répertoire (ça, j'ai vérifié (avec GNU tar (mais ça doit être portable ?))). > Toujours garder un truc a l'esprit avec unix : FAIRE SIMPLE ET FACILE. ![]() Ouaip --- m'enfin, ça peut être facile pas à pas, mais le résultatfinal, hmmm, disons qu'il peut donner une idée de la puissance d'un shell *nix. > Mais par contre, big problem, ca ne va pas rediriger le resultat dans un fichier > mais dans le terminal. Et la ca devient un peu plus complique, du coup. Ah oui, j'avais négligé cet aspect verbose ; bon, insérer un tee dans le pipe doit le faire, tee -f >(la suite du pipe...), ou utiliser les >&3 qu'aime Stéphane Chazelas. >> Pourrait suffire, du moins s'il n'y a pas de saut de ligne dans les noms >> de fichiers, et autres fourberies. Sinon, >> >> find ... -print0 | xargs -0 sed -i -e 'commande' <pas de fichier> > > Ou encore > > find ... -exec sed -i -e "s/truc/blabla/" '{}' ';' Là, c'est moins bien qu'avec xargs, on forke un sed par fichier --- et il vaut mieux «simplequoter» les commandes sed, en général. > et pour ignorer les *.old : > > find ./faq -type f -name "*.old" -prune -o -type f -exec sed ..... '{}' ';' > > Mais comme il y a la redirection a faire, je ferais plutot ceci : > > for i in $(find ./faq -type f -name "*.old" -prune -o -type f) > do > sed blablablablabla $i > $i.new > done > > puis apres verification du resultat : > > for i in **/*.new > do > mv $i ${i/.new$/} > done > > et basta ![]() > > La, c'est tout de suite mieux, non ? Ben non, - tu forkes à gogo ; - tu explores trois fois la même arborescence ; - tu as oublié de quoter les variables, c'est Mal©. ![]() -- Jacques L'helgoualc'h |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Hugues wrote:
> B'jour, lu' > Ou encore > > find ... -exec sed -i -e "s/truc/blabla/" '{}' ';' > > et pour ignorer les *.old : > > find ./faq -type f -name "*.old" -prune -o -type f -exec sed ..... '{}' ';' > et pourqoui ne pas utiliser locate et updatedb si ce couple est installé sur l'Unix en question ? |
|
![]() |
| Outils de la discussion | |
|
|