Forum Programmation.shell action sur le résultat d'une commande

Posté par  .
Étiquettes : aucune
0
12
sept.
2007
Bonjour,

je cherche à supprimer des fichiers dans un répertoire, j'arrive à les lister mais pas à les passer dans la moulinette de rm.
c'est un ls avec plusieurs grep, ex :
ls | grep A | grep -v B | grep .C
et après j'arrive pas à supprimer le résultat.

Pareil avec mv, je veux ajouter une extension à une liste de fichier obtenus avec plusieurs grep.

Merci d'avance.
  • # boucle et commande

    Posté par  . Évalué à 1.

    ma technique perso

    un petit script

    for i in `ls $1 | grep A | grep B | grep -v C | colrm X Y`;do
    rm $i
    done

    qui prend le dossier en parametre ($1)
    fait le filtrage de la liste
    et le rm pour chaque fichier correspondant.

    on peut surement faire plus jolie, plus "propre"
    mais au moins ca marche et comme il est tard,
    je file me coucher.
    • [^] # Re: boucle et commande

      Posté par  . Évalué à 1.

      je ne vois pas quoi faire avec colrm, c'est pour enlever des colonnes ? pour quoi faire ?
      • [^] # Re: boucle et commande

        Posté par  (site web personnel) . Évalué à 1.

        a coup de find peut etre

        man find

        exemple:

        find ./Documents/images/ -name "*.jpg" -exec mv {} {}.plop \;

      • [^] # Re: boucle et commande

        Posté par  . Évalué à 1.

        colrm c'est pour l'exemple

        et oui c'est pour enlever entre le caractere n°X et le caractere n°Y
  • # xargs

    Posté par  . Évalué à 3.

    Sans les mains boucle:
    ls | grep A | grep -v B | grep .C | xargs rm --
    • [^] # Re: xargs

      Posté par  . Évalué à 3.

      Attention aux caractères foireux dans les noms de fichiers (espaces, guillemets, etc. -- enfin pour pas être malin pour mettre des guillemets hein, mais sur des partages samba tout peut arriver :) !

      Pour utiliser xargs de manière plus robuste, il faut demander à ls de quoter/échapper les noms avec -Q (sinon xargs peut couper le nom en deux et rechercher deux fichiers distincts) :
      ls -Q | grep A | grep -v B | grep .C | xargs rm --

      Si on fait un find (cas plus général ?), alors :
      find . -name "toto" -print0 | xargs -0 do_something --

      La doc de xargs indique bien ce problème potentiel [ avec une typo dans ma version, ils parlent de l'option -O mais c'est bien -0 (zéro) ]

      Quand au script avec la boucle 'for' quelques message plus haut, il souffre du même problème et ne fonctionne pas si un nom de fichier contient un espace : le for va faire deux boucles avec les portions de nom...
      Ah les joies du shell ! :(

      • [^] # Re: xargs

        Posté par  . Évalué à 0.

        C'est ça!
        il me manquait le -Q dans ls, car il y a des espaces dans les noms de fichier.
        Merci beaucoup à tous.
        • [^] # find

          Posté par  (site web personnel) . Évalué à 3.

          La bonne solution serait plutôt d'utiliser find,
          ls n'est qu'un outil de *formatage* pour l'utilisateur, il ne devrait pas être utilisé pour les traitements par lots.
          De plus, ls est sensible à l'environnement utilisateur (LS_OPTIONS, TIME_STYLE, etc..). Il faut donc penser à lui demander d'ignorer tout cela, ce qui devient vite fastidieux.

          Ou alors d'utiliser directement l'expansion shell :

          for file in * ; do echo $file | ... ; done

          ça à l'énorme avantage de conserver les échappements. Par contre ça ne prend pas les fichiers commençant par un ".". Et si on fait :

          for file in * .* ; do .... ; done

          s'il n'y a pas de fichiers / dossier qui matche .* ou *, on obtient une erreur, ce qui est gênant.

          en plus, ni cette solution, ni ton ls ne gère le cas où tu te retrouves avec un répertoire dans la liste. Et rm va pas être content, du coup. :-)

          D'où : find est donc la seule vraie bonne solution.

          Ensuite, tous tes grep | grep | grep | ... pourraient être regroupés en deux grep "A|B|C" | grep -v "D|E|F"ce qui serait plus propre.
          Mais comme dit, "find" permet de regrouper tous les matches en une seule commande.

          find -maxdepth 1 -type f ( -name "A" -o -name "B" ) -a ( ! -name "C" -a ! -name "D" ... ) -exec rm '{}' ';'

          à adapter selon tes besoins, évidemment.
          • [^] # Re: find

            Posté par  . Évalué à 1.

            On m'avait déjà dit que find était plus propre.
            Je vais essayer.
            Merci

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.