BASH: comment boucler tous les fichiers dans un ordre trié
je boucle tous les fichiers dans le répertoire avec la commande suivante:
for i in *.fas; do some_code; done;
Cependant, je reçois la commande comme ceci:
vvchr1.saf
vvchr10.saf
vvchr11.saf
au lieu de vvchr1.fas, vvchr2.fas, vvchr3.fas, Quel est l'ordre numérique?
j'ai essayé la commande sort, mais sans succès.
7 réponses
for i in `ls *.fas | sort -V`; do some_code; done;
où sort -V
selon man sort
une version tri - naturel de tri (version) numéros dans le texte
même en utilisant uniquement ls
:
for i in `ls -v *.fas`; do echo $i; done;
vous obtiendrez les fichiers dans L'ordre ASCII. Cela signifie que vvchr10*
vient avant vvchr2*
. Je me rends compte que vous ne pouvez pas renommer vos fichiers (mon cerveau bioinformaticien me dit qu'ils contiennent des données chromosomiques, et nous n'appelons simplement pas le chromosome 1 "chr01"), donc voici une autre solution (ne pas utiliser sort -V
que je ne peux pas trouver sur n'importe quel système d'exploitation que j'utilise):
ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/ /' | sort -k2,2n | tr -d ' ' |
while read filename; do
# do work with $filename
done
ceci est un peu alambiqué et ne fonctionnera pas avec les noms de fichiers contenant des espaces.
une autre solution: Supposons que nous souhaitions itérer les fichiers par ordre de taille, ce qui pourrait être plus approprié pour certaines tâches bioinformatiques:
du *.fas | sort -k2,2n |
while read filesize filename; do
# do work with $filename
done
pour inverser le tri, il suffit d'ajouter r
après -k2,2n
(pour obtenir -k2,2nr
).
avec l'option trier-g il compare selon la valeur numérique générale
for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done
0.journal 1.journal 2.journal ... 10.journal 11.journal
Cela ne fonctionne que si le nom des fichiers numériques. Si ils sont de la chaîne, vous obtiendrez dans l'ordre alphabétique. E. g.:
for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done
raw / 0.journal raw / 10.journal raw / 11.journal ... raw / 2.journal
vous voulez dire que les fichiers avec le numéro 10 viennent avant les fichiers avec le numéro 3 dans votre liste? C'est parce que ls
trie son résultat très simple, donc something-10.whatever
plus petitsomething-3.whatever
.
une solution est de renommer tous les fichiers pour qu'ils aient le même nombre de chiffres (les fichiers avec un seul chiffre dans eux commencent par 0
dans le nombre).
while IFS= read -r file ; do
ls -l "$file" # or whatever
done < <(find . -name '*.fas' 2>/dev/null | sed -r -e 's/([0-9]+)/ /' | sort -k 2 -n | sed -e 's/ //;'
résout le problème, présumant que le nom du fichier reste cohérent, ne s'appuie pas sur des versions très récentes de GNU sort
, ne s'appuie pas sur la lecture de la sortie de ls
et ne pas tomber victime de la conduite-alors que les problèmes.
comme la solution de @Kusalananda (peut-être plus facile à retenir?) mais restauration pour tous les dossiers(?):
array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/ &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done
essentiellement ajouter une clé de tri, Trier, supprimer la clé de tri.
EDIT: déplacé commentaire de solution appropriée
Utilisez le tri-rh et la boucle while
du -sh * | sort -rh | grep -P "avi$" |awk '{print }' | while read f; do fp=`pwd`/$f; echo $fp; done;