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'
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
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 '{}|'
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
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.. Autrement dit, 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
, Oui 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
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