Comment analyser correctement les noms de fichiers dans Bash

Contenu

Bash Shell

Les conventions de nommage des fichiers Bash sont très riches et il est facile de créer un script ou une ligne qui analyse de manière incorrecte les noms de fichiers. Apprenez à analyser correctement les noms de fichiers et, pour cela, assurez-vous que vos scripts fonctionnent comme prévu.

Le problème de l'analyse correcte des noms de fichiers dans Bash

Si vous utilisez Bash depuis un certain temps et que vous écrivez dans son riche langage Bash, vous avez probablement rencontré des problèmes d'analyse de nom de fichier. Jetons un coup d'œil à un exemple simple de ce qui peut mal se passer:

touche 'un
> b'

Définir un fichier avec un caractère CR dans le nom du fichier

Ici, nous créons un fichier qui a un CR (retour de voiture) entré en appuyant sur entrée après le a. Les conventions de nommage des fichiers Bash sont très riches, et même si c'est en quelque sorte cool, nous pouvons utiliser des caractères spéciaux comme ceux-ci dans un nom de fichier, Voyons comment ce fichier se comporte lorsque nous essayons d'effectuer certaines actions dessus:

ls | xargs rm

Le problème en essayant de gérer un nom de fichier qui inclut CR

Ce n'est pas fonctionnel. xargs prendra l'entrée de ls (à travers lui | pipeline) et le passer à rm, Mais quelque chose s'est mal passé dans la procédure!

Ce qui s'est mal passé, c'est que la sortie de ls est pris au pied de la lettre par xargs, et le 'entrer’ (CR – retour de voiture) à l'intérieur du nom de fichier est vu par xargs comme un vrai personnage de fin, pas un CR être passé à rm comme cela devrait être.

Illustrons cela d'une autre manière:

ls | xargs -I{} écho '{}|'

Montrer comment xargs verra le caractère CR comme une nouvelle ligne et divisera les données à son sujet

C’est clair: xargs vous traitez l’entrée sous la forme de deux lignes individuelles, fractionnement du nom de fichier d’origine en deux. Même si nous devions résoudre des problèmes d’espace grâce à une analyse élégante en utilisant la soif, bientôt, nous rencontrions d’autres problèmes lorsque nous commencions à utiliser d’autres caractères spéciaux comme espaces., barres arrière, guillemets et plus encore.

touch 'a
b'
touch 'a b'
touch 'ab'
touch 'a"b'
touch "a’b"
ls

Toutes sortes de caractères spéciaux dans les noms de fichiers.

Même si vous êtes un développeur Bash expérimenté, vous pouvez être secoué en voyant des noms de fichiers comme celui-ci, car ce serait très complexe, pour les outils Bash les plus courants, analyser ces fichiers correctement. Il faudrait faire toutes sortes de modifications de chaîne pour que cela fonctionne.. En d'autres termes, sauf si vous avez la recette secrète.

Avant de nous plonger là-dedans, il y a encore une chose, quelque chose que vous devriez savoir, vous pouvez rencontrer en analysant ls production. Si vous utilisez un codage couleur pour les listes de répertoires, qui est activé par défaut dans Ubuntu, il est facile d'exécuter un autre ensemble de ls problèmes d'analyse.

Ceux-ci ne sont pas vraiment liés à la façon dont les fichiers sont nommés, mais plutôt avec la façon dont les fichiers sont présentés en sortie de ls. Les ls la sortie contiendra des codes hexadécimaux représentant la couleur à utiliser dans votre terminal.

Pour éviter de rencontrer ces, il suffit d'utiliser --color=never en option pour ls:
ls --color=never.

et menthe 20 (un excellent système d'exploitation dérivé d'Ubuntu), ce problème semble résolu, même s'il est possible que le problème soit toujours présent dans de nombreuses autres versions d'Ubuntu ou plus anciennes, etc. J'ai vu ce problème à la mi-août 2020 sous Ubuntu.

Même si vous n'utilisez pas de code couleur pour vos listes de répertoires, votre script est susceptible de s'exécuter sur d'autres systèmes qui ne sont pas détenus ou gérés par vous. Dans ce cas, vous voudrez également utiliser cette option pour empêcher les utilisateurs de cette machine de rencontrer le problème décrit.

Revenons à notre recette secrète, Voyons comment nous pouvons nous assurer que nous n'aurons pas de problèmes avec les caractères spéciaux dans les noms de fichiers Bash. La réponse fournie évite toute utilisation de ls, que tu ferais bien d'éviter en général, donc les problèmes de codage couleur ne sont pas non plus applicables.

Il y a encore des moments où ls L'analyse est rapide et pratique, mais ce sera toujours compliqué et probablement "sale"’ dès que des caractères spéciaux sont saisis, sans oublier qu'ils sont dangereux (les caractères spéciaux peuvent être utilisés pour introduire toutes sortes de problèmes).

La recette secrète: NULL résiliation

Les développeurs d'outils Bash ont réalisé ce même problème de nombreuses années auparavant et nous ont fourni: NULL Résiliation!

Qu'est que c'est NULL questions d'achèvement? Considérez comment dans les exemples ci-dessus, CR (le littéralement entrer dans) était le personnage principal de la fin.

Nous avons également vu comment vous pouvez utiliser des caractères spéciaux tels que des guillemets, espaces et barres obliques inverses dans les noms de fichiers, même s'ils ont des fonctions spéciales en ce qui concerne d'autres outils d'analyse et de modification de texte Bash comme sed. Maintenant, comparez cela avec le -0 option une xargs, de man xargs:

-0, -nul Les éléments d'entrée se terminent par un caractère nul au lieu d'un espace vide, et les guillemets et la barre oblique inverse ne sont pas spéciaux (tous les caractères sont pris au pied de la lettre). Désactiver la chaîne de fin de fichier, qui est traité comme n'importe quel autre argument. Utile lorsque les éléments d'entrée peuvent contenir des blancs, guillemets ou barres obliques inverses. L'option GNU find -print0 produit une entrée appropriée pour ce mode.

Et le -print0 option une find, de man find:

-fprint0 archive Certain; imprime le nom complet du fichier sur la sortie standard, suivi d'un caractère nul (au lieu du caractère de nouvelle ligne qui utilise -print). Cela permet aux programmes qui traitent la sortie de recherche d'interpréter correctement les noms de fichiers qui contiennent de nouvelles lignes ou d'autres types d'espaces blancs.. Cette option correspond à l'option -0 de xargs.

Les Certain; ici signifie Si l'option est spécifiée, ce qui suit est vrai;. Les deux avertissements clairs qui sont donnés dans d'autres parties de la même page de manuel sont également intéressants.:

  • Si vous redirigez la sortie de find vers un autre programme et qu'il y a la moindre chance que les fichiers que vous recherchez contiennent une nouvelle ligne, alors vous devriez sérieusement envisager d'utiliser l'option -print0 au lieu de -print. Voir la section NOMS DE FICHIER INHABITUELS pour plus d'informations sur la façon dont les caractères inhabituels sont traités dans les noms de fichier..
  • Si vous utilisez la recherche dans un script ou dans une situation où les fichiers correspondants peuvent avoir des noms arbitraires, vous devriez envisager d’utiliser -print0 au lieu de -print.

Ces avertissements clairs nous rappellent que l’analyse des noms de fichiers en bash peut être, Et c'est, une entreprise compliquée. Malgré cela, avec les bonnes alternatives pour find, a savoir -print0, et xargs, a savoir -0, tous nos caractères spéciaux contenant des noms de fichiers peuvent être analysés correctement:

ls
find . -name 'a*' -print0 
find . -nom 'a*' -print0 | xargs -0 ls
find . -nom 'a*' -print0 | xargs -0 rm

La solution: find -print0 et xargs -0

Tout d’abord, nous examinons notre liste d’annuaires. Tous nos noms de fichiers contenant des caractères spéciaux sont là. Ensuite, nous faisons un simple find ... -print0 pour voir la sortie. On constate que les cordes sont NULL fini (avec lui NULL O – le même caractère – invisible).

Notons aussi qu'il n'y a qu'un CR a la sortie, qui correspond au single CR que nous avions entré dans le premier nom de fichier, composé par une suivi par entrer dans suivi par B.

Pour terminer, la sortie n'introduit pas de nouvelle ligne (qui contient également CR) avant de retourner le $ indicateur de borne, puisque les chaînes étaient NULL et non CR fini. Nous appuyons sur Entrée dans le $ invite du terminal pour expliquer un peu les choses.

Puis on ajoute xargs avec lui -0 options, ce qui permet xargs pour gérer le NULL fini l'entrée correctement. Nous voyons que l'entrée transmise et reçue de ls c'est clair et il n'y a pas d'altération de la transformation du texte.

Pour finir on réessaye notre rm commander, et cette fois pour tous les fichiers, y compris l'original contenant le CR avec qui nous avons eu des problèmes. Les rm fonctionne très bien et il n'y a pas d'erreurs ou de problèmes d'analyse. Excellent!

Fin

Nous avons vu combien essentiel, dans plusieurs cas, analyser et gérer correctement les noms de fichiers dans bash. En apprenant à utiliser find correctement est un peu plus difficile que de simplement utiliser ls, les avantages qu'il procure peuvent finir par payer. Plus de sécurité et sans problème avec les caractères spéciaux.

Si vous avez apprécié ce post, vous pouvez également lire Comment renommer des fichiers en noms de fichiers numériques sous Linux, montrant un intéressant et quelque peu complexe find -print0 | xargs -0 déclaration. Prendre plaisir!

Abonnez-vous à notre newsletter

Nous ne vous enverrons pas de courrier SPAM. Nous le détestons autant que vous.