Quelqu'un a-t-il un modèle de script Shell pour faire quelque chose avec ls
pour obtenir une liste de noms de répertoires et les parcourir en boucle pour ensuite faire quelque chose?
Je prévois de faire ls -1d */
pour obtenir la liste des noms de répertoire.
Édité pour ne pas utiliser ls là où un glob ferait, comme @ shawn-j-goff et d'autres ont suggéré.
Utilisez simplement une boucle for..do..done
:
for f in *; do
echo "File -> $f"
done
Vous pouvez remplacer le *
par le *.txt
ou tout autre objet renvoyant une liste (de fichiers, de répertoires ou quoi que ce soit d'autre), une commande générant une liste, par exemple, $(cat filelist.txt)
, ou le remplacer par une liste.
Dans la boucle do
, vous faites simplement référence à la variable de boucle avec le préfixe du signe dollar (donc $f
dans l'exemple ci-dessus). Vous pouvez echo
ou faire tout ce que vous voulez.
Par exemple, pour renommer tous les fichiers .xml
du répertoire actuel en .txt
:
for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done
Ou mieux encore, si vous utilisez Bash, vous pouvez utiliser les extensions de paramètre Bash plutôt que de générer un sous-shell:
for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done
Pour les fichiers contenant des espaces, vous devrez vous assurer de citer la variable comme suit:
for i in $(ls); do echo "$i"; done;
ou, vous pouvez modifier la variable d'environnement IFS (Input Field Separator):
IFS=$'\n';for file in $(ls); do echo $i; done
Enfin, selon ce que vous faites, vous n’avez peut-être même pas besoin du ls:
for i in *; do echo "$i"; done;
Si vous avez GNU Parallel http://www.gnu.org/software/parallel/ installé, vous pouvez le faire:
ls | parallel echo {} is in this dir
Pour renommer tous les fichiers .txt en .xml:
ls *.txt | parallel mv {} {.}.xml
Regardez la vidéo d'introduction de GNU Parallel pour en savoir plus: http://www.youtube.com/watch?v=OpaiGYxkSuQ
Pour ajouter à la réponse de CoverosGene, voici un moyen de ne lister que les noms de répertoires:
for f in */; do
echo "Directory -> $f"
done
Pourquoi ne pas définir IFS sur une nouvelle ligne, puis capturer la sortie de ls
dans un tableau? Définir IFS sur newline devrait résoudre les problèmes de caractères amusants dans les noms de fichiers; utiliser ls
peut être Nice car il dispose d’une fonction de tri intégrée.
(Lors des tests, je rencontrais des difficultés pour définir IFS sur \n
, mais le réglage sur newline backspace fonctionne, comme suggéré ailleurs ici):
Par exemple. (en supposant que le modèle de recherche ls
souhaité soit passé dans $1
):
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
FILES=($(/bin/ls "$1"))
for AFILE in ${FILES[@]}
do
... do something with a file ...
done
IFS=$SAVEIFS
Ceci est particulièrement pratique sous OS X, par exemple pour capturer une liste de fichiers triés par date de création (du plus ancien au plus récent), la commande ls
est ls -t -U -r
.