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;