Agence web » Actualités du digital » Comment analyser correctement les noms de fichiers dans Bash –

Comment analyser correctement les noms de fichiers dans Bash –

une-breve-histoire-d39unix-cloudsavvy-it-7337062

Les conventions de dénomination des fichiers Bash sont très riches et il est facile de créer un script ou une seule ligne qui analyse de manière incorrecte les noms de fichiers. Apprenez à analyser correctement les noms de fichiers et assurez-vous ainsi 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 avez écrit des scripts dans son riche langage Bash, vous aurez probablement rencontré des problèmes d’analyse de nom de fichier. Jetons un coup d’œil à un exemple simple de ce qui peut mal tourner:

touch 'a
> b'

Configuration d'un fichier avec un caractère CR dans le nom de fichier

Ici, nous avons créé un fichier qui a un réel CR (retour chariot) introduit en appuyant sur Entrée après le a. Les conventions de dénomination des fichiers Bash sont très riches, et bien que cela soit cool à certains égards, 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 de prendre des mesures dessus:

ls | xargs rm

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

Cela n’a pas fonctionné. xargs prendra l’entrée de ls (via le | pipe), et passez-le à rm, mais quelque chose a mal tourné dans le processus!

Ce qui ne va pas, c’est que la sortie de ls est pris littéralement par xargs, et le ‘enter’ (CR – Retour chariot) dans le nom de fichier est vu par xargs comme un caractère de terminaison réel, pas un CR à transmettre rm comme cela devrait être.

Illustrons cela d’une autre manière:

ls | xargs -I{} echo '{}|'

Montrant comment xargs verra le caractère CR comme une nouvelle ligne et divisera les données dessus

C’est clair: xargs traite l’entrée en deux lignes individuelles, divisant le nom de fichier d’origine en deux! Même si nous devions résoudre les problèmes d’espace par une analyse sophistiquée à l’aide de sed, nous rencontrerions bientôt d’autres problèmes lorsque nous commencerons à utiliser d’autres caractères spéciaux tels que des espaces, des barres obliques inverses, des 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 chevronné, vous pouvez frissonner en voyant des noms de fichiers comme celui-ci, car il serait très complexe, pour la plupart des outils Bash courants, d’analyser correctement ces fichiers. Vous auriez à faire toutes sortes de modifications de chaîne pour que cela fonctionne. Autrement dit, à moins que vous n’ayez la recette secrète.

Avant de plonger dans cela, il y a encore une chose – un must-know – que vous pouvez rencontrer lors de l’analyse ls production. Si vous utilisez un code couleur pour les listes de répertoires, qui est activé par défaut sur Ubuntu, il est facile d’exécuter dans un autre ensemble de ls problèmes d’analyse.

Celles-ci ne sont pas vraiment liées à la façon dont les fichiers sont nommés, mais plutôt à la façon dont les fichiers sont présentés en sortie de ls. le ls la sortie contiendra des codes hexadécimaux qui représentent la couleur à utiliser sur votre terminal.

Pour éviter de les rencontrer, utilisez simplement --color=never en option pour ls:
ls --color=never.

Dans Mint 20 (un excellent système d’exploitation dérivé d’Ubuntu), ce problème semble résolu, bien que le problème puisse toujours être présent dans de nombreuses autres versions ou plus anciennes d’Ubuntu, etc. J’ai vu ce problème aussi récent que mi-août 2020 sur Ubuntu.

Même si vous n’utilisez pas de code couleur pour vos listes de répertoires, il est possible que votre script s’exécute sur d’autres systèmes que vous ne possédez pas ou ne gérez pas. Dans un tel cas, vous souhaiterez également utiliser cette option pour empêcher les utilisateurs d’une telle machine de s’exécuter dans le problème décrit.

Revenant à notre recette secrète, voyons comment nous pouvons nous assurer que nous n’aurons aucun problème avec les caractères spéciaux dans les noms de fichiers Bash. La solution fournie évite toute utilisation de ls, ce que l’on ferait bien d’éviter en général, de sorte que 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 elle sera toujours délicate et probablement «sale» dès que des caractères spéciaux sont introduits – sans parler de l’insécurité (les caractères spéciaux peuvent être utilisés pour introduire toutes sortes de problèmes).

La recette secrète: la résiliation NULL

Les développeurs d’outils Bash ont réalisé ce même problème plusieurs années plus tôt et nous ont fourni: NULL Résiliation!

Quel est NULL résiliation vous demandez-vous? Considérez comment dans les exemples ci-dessus, CR (ou littéralement entrer) était le principal personnage de terminaison.

Nous avons également vu comment des caractères spéciaux comme les guillemets, les espaces blancs et les barres obliques inverses peuvent être utilisés dans les noms de fichiers, même s’ils ont des fonctions spéciales lorsqu’il s’agit d’autres outils d’analyse et de modification de texte Bash comme sed. Maintenant, comparez cela avec le -0 option pour xargs, de man xargs:

-0, –null Les éléments d’entrée sont terminés par un caractère nul au lieu d’un espace blanc, et les guillemets et la barre oblique inverse ne sont pas spéciaux (chaque caractère est pris littéralement). Désactive la fin de la chaîne de fichier, qui est traitée comme tout autre argument. Utile lorsque les éléments d’entrée peuvent contenir des espaces, des guillemets ou des barres obliques inverses. L’option GNU find -print0 produit une entrée adaptée à ce mode.

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

-fprint0 fichier Vrai; imprime le nom complet du fichier sur la sortie standard, suivi d’un caractère nul (au lieu du caractère de nouvelle ligne utilisé par -print). Cela permet aux noms de fichiers qui contiennent des retours à la ligne ou d’autres types d’espace blanc d’être correctement interprétés par les programmes qui traitent la sortie de recherche. Cette option correspond à l’option -0 de xargs.

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

  • Si vous transférez la sortie de find dans un autre programme et qu’il y a la moindre possibilité que les fichiers que vous recherchez contiennent une nouvelle ligne, vous devriez sérieusement envisager d’utiliser l’option -print0 au lieu de -print. Consultez la section NOMS DE FICHIER INHABITUELS pour plus d’informations sur la manière dont les caractères inhabituels dans les noms de fichiers sont traités.
  • Si vous utilisez find dans un script ou dans une situation où les fichiers correspondants peuvent avoir des noms arbitraires, vous devez envisager d’utiliser -print0 au lieu de -print.

Ces avertissements clairs nous rappellent que l’analyse des noms de fichiers dans bash peut être, et reste, une affaire délicate. Cependant, avec les bonnes options pour find, à savoir -print0, et xargs, à savoir -0, tous nos caractères spéciaux contenant des noms de fichiers peuvent être analysés correctement:

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

La solution: trouver -print0 et xargs -0

Nous vérifions d’abord notre liste d’annuaire. Tous nos noms de fichiers contenant des caractères spéciaux sont là. Nous faisons ensuite un simple find ... -print0 pour voir la sortie. Nous notons que les chaînes sont NULL terminé (avec le NULL ou – le même caractère – non visible).

On note également qu’il existe un seul CR dans la sortie, qui correspond au single CR nous avions introduit dans le premier nom de fichier, composé de une suivi par entrer suivi par b.

Enfin, la sortie n’introduit pas de nouvelle ligne (contenant également CR) avant de retourner le $ invite du terminal, comme les chaînes étaient NULL et pas CR terminé. Nous appuyons sur Entrée au $ invite du terminal pour rendre les choses un peu plus claires.

Ensuite, nous ajoutons xargs avec le -0 options, ce qui permet xargs pour gérer le NULL entrée correctement terminée. Nous voyons que l’entrée transmise et reçue de ls semble clair et il n’y a pas de mutilation de transformation du texte en cours.

Enfin, nous réessayons notre rm commande, et cette fois pour tous les fichiers dont celui d’origine contenant le CR avec lequel nous avons eu des problèmes. le rm fonctionne parfaitement et aucune erreur ou problème d’analyse n’est observé. Génial!

Emballer

Nous avons vu à quel point il est important, dans de nombreux cas, d’analyser et de gérer correctement les noms de fichiers dans Bash. Alors qu’apprendre à utiliser find correctement est un peu plus difficile que d’utiliser simplement ls, les avantages qu’il offre peuvent finalement porter leurs fruits. Sécurité accrue et aucun problème avec les caractères spéciaux.

Si vous avez apprécié cet article, vous voudrez peut-être également lire Comment renommer en bloc des fichiers en noms de fichiers numériques sous Linux, qui montre un élément intéressant et quelque peu complexe find -print0 | xargs -0 déclaration. Prendre plaisir!

★★★★★