Quelqu'un a-t-il un modèle de script shell permettant de créer ls
une liste de noms de répertoires et de les parcourir en boucle?
Je prévois de faire ls -1d */
pour obtenir la liste des noms de répertoires.
la source
Quelqu'un a-t-il un modèle de script shell permettant de créer ls
une liste de noms de répertoires et de les parcourir en boucle?
Je prévois de faire ls -1d */
pour obtenir la liste des noms de répertoires.
Ne pas utiliser ls à la place d'un glob, comme @ shawn-j-goff et d'autres l'ont suggéré.
Il suffit d'utiliser une for..do..done
boucle:
for f in *; do
echo "File -> $f"
done
Vous pouvez remplacer le *
with *.txt
ou tout autre glob qui retourne une liste (de fichiers, répertoires ou quoi que ce soit d'autre), une commande qui génère une liste, par exemple $(cat filelist.txt)
, ou bien la remplacer par une liste.
Dans la do
boucle, vous faites simplement référence à la variable de boucle avec le préfixe du signe dollar (comme $f
dans l'exemple ci-dessus). Vous pouvez echo
le faire ou faire tout ce que vous voulez.
Par exemple, pour renommer tous les .xml
fichiers du répertoire en cours 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ètres 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
for
boucles et le piège typique d’essayer d’analyser la sortie dels
. @ DanielA.White, vous pouvez envisager d’accepter cette réponse si elle n’est pas utile (ou si elle est potentiellement trompeuse), car, comme vous l’avez dit, vous agissez sur des annuaires. La réponse de Shawn J. Goff devrait fournir une solution plus robuste et plus efficace à votre problème.ls
sortie , vous ne devriez pas lire la sortie dans unefor
boucle , vous devriez utiliser à la$()
place de `` et Use More Quotes ™ . Je suis sûr que @CoverosGene était bien intentionné, mais c’est terrible.ls
estls -1 | while read line; do stuff; done
. Au moins celui-ci ne cassera pas pour les espaces blancs.mv -v
vous n'avez pas besoinecho "moved $x -> $t"
Utiliser la sortie de
ls
pour obtenir les noms de fichiers est une mauvaise idée . Cela peut conduire à des scripts défectueux et même dangereux. En effet , un nom de fichier peut contenir des caractères à l' exception/
et lenull
caractère, etls
ne pas utiliser l' un de ces personnages comme délimiteurs, donc si un nom de fichier a un espace ou un saut de ligne, vous sera obtenir des résultats inattendus.Il existe deux très bons moyens de parcourir les fichiers. Ici, j’ai simplement utilisé
echo
pour montrer comment faire quelque chose avec le nom de fichier; vous pouvez utiliser n'importe quoi, cependant.La première consiste à utiliser les fonctions de globbing natives du shell.
Le shell se développe
*/
en arguments séparés lus par lafor
boucle; même s'il y a un espace, une nouvelle ligne ou tout autre caractère étrange dans le nom du fichier,for
chaque nom complet sera vu comme une unité atomique; ce n'est pas analyser la liste en aucune façon.Si vous voulez aller récursivement dans les sous-répertoires, cela ne fonctionnera que si votre shell dispose de fonctionnalités étendues (telles que celles
bash
deglobstar
.). Si votre shell n'a pas ces fonctionnalités, ou si vous voulez vous assurer que votre script fonctionnera Sur une variété de systèmes, l'option suivante consiste à utiliserfind
.Ici, la
find
commande appelleraecho
et lui passera un argument du nom de fichier. Il le fait une fois pour chaque fichier trouvé. Comme dans l'exemple précédent, il n'y a pas d'analyse d'une liste de noms de fichiers; au lieu de cela, un nom de fichier est envoyé complètement comme argument.La syntaxe de l'
-exec
argument semble un peu drôle.find
prend le premier argument après-exec
et traite cela comme le programme à exécuter, et chaque argument suivant, il le prend comme argument à transmettre à ce programme. Il y a deux arguments spéciaux-exec
à voir. Le premier est{}
; cet argument est remplacé par un nom de fichierfind
généré par les parties précédentes . La seconde est;
, ce qui permet defind
savoir que ceci est la fin de la liste des arguments à transmettre au programme;find
a besoin de cela car vous pouvez continuer avec plus d’argumentsfind
destinés au programme exec'd et non au programme exec'd. La raison en\
est que la coquille traite également;
spécialement - il représente la fin d'une commande, nous avons donc besoin de l'échapper pour que le shell l'envoie comme argumentfind
plutôt que de le consommer pour lui-même; Une autre façon de faire en sorte que la coquille ne la traite pas spécialement est de la mettre entre guillemets: cela';'
fonctionne aussi bien que\;
pour le faire.la source
find
. Il est possible de faire de la magie et même de-exec
contourner les limites perçues . Cette-print0
option est également utile à utiliser avecxargs
.Pour les fichiers contenant des espaces, vous devrez vous assurer de citer la variable comme suit:
ou, vous pouvez modifier la variable d'environnement IFS (Input Field Separator):
Enfin, selon ce que vous faites, vous n’avez peut-être même pas besoin du ls:
la source
\n
est insuffisante. Ce n'est jamais une bonne idée de recommander l'analyse de la sortie dels
.Si vous avez installé GNU Parallel http://www.gnu.org/software/parallel/, vous pouvez le faire:
Pour renommer tous les fichiers .txt en .xml:
Regardez la vidéo d'introduction de GNU Parallel pour en savoir plus: http://www.youtube.com/watch?v=OpaiGYxkSuQ
la source
Pour ajouter à la réponse de CoverosGene, voici un moyen de ne lister que les noms de répertoires:
la source
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; utiliserls
peut être agréable car il dispose d’une fonction de tri intégrée.(Lors des tests, j'avais du mal à définir IFS sur,
\n
mais le réglage sur newline backspace fonctionne, comme suggéré ailleurs ici):Par exemple (en supposant que le
ls
modèle de recherche souhaité a été transmis$1
):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
ls
commande estls -t -U -r
.la source
\n
est insuffisante. Les seules solutions valides utilisent une boucle for avec extension de nom de chemin, oufind
.Voici comment je le fais, mais il existe probablement des moyens plus efficaces.
la source
ls | while read i; do echo filename: $i; done