GNU/Linux >> Tutoriels Linux >  >> Linux

Comment analyser la sortie de la commande find lorsque les noms de fichiers contiennent des espaces ?

Idéalement, vous ne le faites pas du tout de cette façon, car il est toujours difficile d'analyser correctement les noms de fichiers dans un script shell (réparez-le pour les espaces, vous aurez toujours des problèmes avec d'autres caractères intégrés, en particulier la nouvelle ligne). Ceci est même répertorié comme la première entrée de la page BashPitfalls.

Cela dit, il existe un moyen de faire presque ce que vous voulez :

oIFS=$IFS
IFS=$'\n'

find . -name '*.txt' | while read -r i; do
  # use "$i" with whatever you're doing
done

IFS=$oIFS

N'oubliez pas de citer également $i lors de son utilisation, pour éviter que d'autres choses n'interprètent les espaces plus tard. N'oubliez pas également de définir $IFS de retour après l'avoir utilisé, car ne pas le faire entraînera des erreurs déconcertantes plus tard.

Ceci a une autre mise en garde :que se passe-t-il à l'intérieur du while loop peut avoir lieu dans un sous-shell, selon le shell exact que vous utilisez, de sorte que les paramètres variables peuvent ne pas persister. Le for la version boucle évite cela mais au prix que, même si vous appliquez le $IFS solution pour éviter les problèmes d'espaces, vous aurez alors des ennuis si le find renvoie trop de fichiers.

À un moment donné, la solution correcte pour tout cela devient de le faire dans un langage tel que Perl ou Python au lieu de shell.


Utilisez find -print0 et dirigez-le vers xargs -0 , ou écrivez votre propre petit programme C et dirigez-le vers votre petit programme C. C'est ce que -print0 et -0 ont été inventés pour.

Les scripts shell ne sont pas la meilleure façon de gérer les noms de fichiers contenant des espaces :vous pouvez le faire, mais cela devient maladroit.


Vous pouvez définir le "séparateur de champ interne" (IFS ) à autre chose qu'un espace pour le fractionnement de l'argument de la boucle, par exemple

ORIGIFS=${IFS}
NL='
'
IFS=${NL}
for i in $(find . -name '*.txt'); do
    IFS=${ORIGIFS}
    #do stuff
done
IFS=${ORIGIFS}

J'ai réinitialisé IFS après son utilisation en trouvaille, surtout parce que ça a l'air sympa, je trouve. Je n'ai vu aucun problème à le définir sur nouvelle ligne, mais je pense que c'est "plus propre".

Une autre méthode, selon ce que vous voulez faire avec la sortie de find , est soit d'utiliser directement -exec avec le find ou utilisez -print0 et dirigez-le vers xargs -0 . Dans le premier cas find prend soin de l'échappement du nom de fichier. Dans le -print0 cas, find imprime sa sortie avec un séparateur nul, puis xargs se divise à ce sujet. Comme aucun nom de fichier ne peut contenir ce caractère (ce que je sais), c'est toujours sûr également. Ceci est surtout utile dans des cas simples; et n'est généralement pas un excellent substitut pour un for complet boucle.


Linux
  1. Comment arrêter la commande de recherche après la première correspondance ?

  2. Comment définir une variable égale à la sortie d'une commande dans Grub2 ?

  3. Comment utiliser la commande Linux find pour rechercher des fichiers

  4. Comment spécifiez-vous les noms de fichiers dans un zip lors de sa création sur la ligne de commande à partir d'un tube ?

  5. Comment rediriger la sortie d'une commande vers un fichier lorsque la commande demandera des entrées utilisateur ?

Comment rechercher des fichiers sous Linux avec la commande Find

Comment changer la couleur de sortie de 'Echo' sous Linux

Comment rechercher des fichiers avec la commande fd sous Linux

Comment trouver l'utilisation du processeur, ce qui fait que le système se bloque

Que signifie le symbole du tuyau linux | fais?

Comment lire la colonne IDLE dans la sortie de la commande Linux 'w' ?