Forum Programmation.shell problème find et espaces dans les noms de fichiers

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
2
oct.
2019

Bonjour

Ce code coupe les fichiers au niveau des espaces dans les noms :

for fichier in $(find * -maxdepth 0 -prune -type f )
si je fais :

IFS='
'
for fichier in $(find * -maxdepth 0 -prune -type f ) ça fonctionne.

J'aimerais savoir s'il n'y a pas un autres moyen que le changement de l'ISF pour faire marcher cette ligne.

Merci

  • # -print0 ?

    Posté par  . Évalué à 3.

    j'ai l'impression de manquer un peu de contexte pour savoir si je ne réponds pas à côté de la plaque, mais find dispose de l'option print0 qui permet de séparer les objets trouvés par le caractère nul plutôt que l'espace. Il faut du coup utiliser quelque chose qui sait se débrouiller avec des éléments séparés par des caractères nuls plutôt que des espaces (souvent, c'est xargs avec l'option -0).

    Difficile d'en dire plus sans savoir comment ça s'intègre dans ce que tu essaies de faire.

  • # Plusieurs solutions

    Posté par  (site web personnel) . Évalué à 5. Dernière modification le 02 octobre 2019 à 18:11.

    mkdir toto && cd toto
    touch "bla bla"
    touch "bli bli"
    find . -type f -print0 | xargs --null ls -l         # un seul processus ls consommant les données
    find . -type f -exec ls -l {} \;                    # un processus ls par fichier
    for f in "$(find . -type f)"; do ls -l "$f" ; done  # un processus ls par fichier

    Souvent la méthode avec xargs est mieux (un seul processus lancé), sauf dans le cas où tu as beaucoup de fichiers et tu risques de dépasser la liste d'arguments maximale qu'on peut passer à un process.

    Autre liste de méthodes ici:
    https://stackoverflow.com/questions/9612090/how-to-loop-through-file-names-returned-by-find

    Je note sur leur réponse que tu peux te passer de find en utilisant shopt -s globstar et glober en récursif avec **/*.

    • [^] # Re: Plusieurs solutions

      Posté par  . Évalué à 1.

      Bonjour

      Désolé de répondre un peu tard. Merci pour ces différentes solutions qui fonctionnent parfaitement dans mon cas.

    • [^] # Re: Plusieurs solutions

      Posté par  . Évalué à 1. Dernière modification le 05 octobre 2019 à 10:58.

      Re :

      Si je fais par exemple

      for f in "$(find * -maxdepth 0 -type f)"; do echo "$f"; echo "fin de ligne"; done

      ça me donne bien la liste souhaité, mais le "fin de ligne ne s'affiche qu'une fois à la fin de la liste alors qu'il se trouve bien dans la boucle 'for'. Problème de syntaxe ?

      • [^] # Re: Plusieurs solutions

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

        La boucle n'est pas bonne, il suffit d'ajouter un peu de texte autour de $f pour s'en convaincre :

        for f in "$(find * -maxdepth 0 -type f)"; do echo "1 seul résultat >>>$f<<<"; echo "fin de ligne"; done

        Normal : le résultat de find est encadré par des guillemets, for opère sur un seul mot, donc un seul tour de boucle.

        Au passage, je ne comprends pas à quoi sert find * plutôt que find. Cela va même provoquer une erreur quand un répertoire est vide, puisque * ne sera pas remplacé, donc find va essayer de travailler sur (littéralement) *

        Debian Consultant @ DEBAMAX

        • [^] # Re: Plusieurs solutions

          Posté par  (site web personnel) . Évalué à 2. Dernière modification le 07 octobre 2019 à 16:14.

          Ah, effectivement, mea culpa. Mais on ne peut pas non plus enlever les guillemets autour du $(find ...) car alors on ne gère plus les fichiers ayant un espace dans leur nom.

          • [^] # Re: Plusieurs solutions

            Posté par  (site web personnel) . Évalué à 1. Dernière modification le 07 octobre 2019 à 18:46.

            C'est donc une mauvaise solution, puisque cela met en place une boucle qui ne fait qu'un seul tour de boucle avec comme seul objet la concaténation de l'ensemble de la sortie de find, non ?

            Debian Consultant @ DEBAMAX

  • # Commentaire supprimé

    Posté par  . Évalué à 1.

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Commentaire supprimé

      Posté par  . Évalué à 1.

      Ce commentaire a été supprimé par l’équipe de modération.

  • # re : problème supplémentaire

    Posté par  . Évalué à 1.

    Merci pour les différentes solutions mais du coup j'ai un problème supplémentaire :

    Si je fais par exemple

    for f in "$(find * -maxdepth 0 -type f)"; do echo "$f"; echo "fin de ligne"; done

    j'obtiens bien la liste souhaité, mais le "fin de ligne ne s'affiche qu'une fois à la fin de la liste alors qu'il se trouve bien dans la boucle 'for'. Problème de syntaxe ?

Suivre le flux des commentaires

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