[Memo] BASH SHELL - se moquer des espaces blancs dans un for
13 Janvier 2010 20:14 | Par Miss Lemon dans Linux
Dans les variables internes des scripts BASH on connaissait:
Je vous présente $IFS.
$IFS détermine la façon dont Bash reconnaît les champs ou les limites de mots lorsqu'il interprète des chaînes de caractères. La valeur par défaut est un espace blanc (espace, tabulation et retour chariot) mais peut être changé, par exemple, pour analyser un fichier de données séparées par des virgules.
Cette variable peut être utile lorsque vous souhaitez traiter un fichier ligne par ligne, et que ces même lignes comportent des espaces.
Pour des besoins personnels, je souhaitez exécuter un ensemble de commande sur une liste de fichiers récupérés via la commande find à partir d'un for.
Malheureusement pour moi, certains de ces fichiers possédaient des espaces dans leur nom.
Mon script initial était comme suit:
Malheureusement, les espaces contenus dans les noms empêchaient que la commande s'exécute correctement:
Ce qui dans mon cas concret nous donne :
MAJ du 15/01/2010:
En partant du fait que iL vaut mieux faire 1 zip de 100 fichiers, plutôt que 100 zip de 1 fichiers, la boucle for est à utiliser avec modération.
Dans certains cas il est donc plus judicieux d'utiliser xargs qui possède une option nous permettant de spécifier le champs séparateur.
- $HOME - le répertoire personnel de l'utilisateur
- $BASH - le chemin vers le binaire Bash
- $GROUPS - les groupes auxquels appartient l'utilisateur
- ...
Je vous présente $IFS.
$IFS détermine la façon dont Bash reconnaît les champs ou les limites de mots lorsqu'il interprète des chaînes de caractères. La valeur par défaut est un espace blanc (espace, tabulation et retour chariot) mais peut être changé, par exemple, pour analyser un fichier de données séparées par des virgules.
Cette variable peut être utile lorsque vous souhaitez traiter un fichier ligne par ligne, et que ces même lignes comportent des espaces.
Pour des besoins personnels, je souhaitez exécuter un ensemble de commande sur une liste de fichiers récupérés via la commande find à partir d'un for.
Malheureusement pour moi, certains de ces fichiers possédaient des espaces dans leur nom.
$ find . -type f mon fichier 1.doc mon fichier 2.pdf
Mon script initial était comme suit:
for i in $(find . -type f)
do
zip all_files.zip $i
done
(Il était un peu plus compliqué que ça en fait mais je simplifie pour l'exemple ;) )
Malheureusement, les espaces contenus dans les noms empêchaient que la commande s'exécute correctement:
zip warning: name not matched: ./zip all_files.zip mon zip error: Nothing to do! (all_files.zip) zip warning: name not matched: ./zip all_files.zip fichier zip error: Nothing to do! (all_files.zip) zip warning: name not matched: ./zip all_files.zip 1.doc zip error: Nothing to do! (all_files.zip) zip warning: name not matched: ./zip all_files.zip mon zip error: Nothing to do! (all_files.zip) zip warning: name not matched: ./zip all_files.zip fichier zip error: Nothing to do! (all_files.zip) zip warning: name not matched: ./zip all_files.zip 2.pdf zip error: Nothing to do! (all_files.zip)Grâce à la variable $IFS, j'ai pu obtenir le résultat que je voulais, avec le script suivant
oldIFS=$IFS # sauvegarde du séparateur de champ
IFS=$'\n' # nouveau séparateur de champ, le caractère fin de ligne
for i in $(find . -type f)
do
zip all_files.zip $i
done
IFS=$old_IFS # rétablissement du séparateur de champ par défaut
Par défaut $IFS contient l'espace comme séparateur de champs. En lui affectant le caractère de fin de ligne, le bash ne considérera plus que le nom de fichier sera terminé lorsqu'il rencontrera un espace.Ce qui dans mon cas concret nous donne :
adding: zip all_files.zip mon fichier 1.doc (deflated xx%) adding: zip all_files.zip mon fichier 2.pdf (deflated xx%)Et voilà !
MAJ du 15/01/2010:
En partant du fait que iL vaut mieux faire 1 zip de 100 fichiers, plutôt que 100 zip de 1 fichiers, la boucle for est à utiliser avec modération.
Dans certains cas il est donc plus judicieux d'utiliser xargs qui possède une option nous permettant de spécifier le champs séparateur.
find -type f | xargs -d "\n" zip all_files.zip
Merci Nico P. pour cette option qui m'avait échappée










