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.

37
demandé sur ROMANIA_engineer 2011-11-03 13:35:09

7 réponses

for i in `ls *.fas | sort -V`; do some_code; done;

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;
66
répondu catalin.costache 2011-11-03 09:52:42

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).

4
répondu Kusalananda 2011-11-03 10:07:10

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

3
répondu gtangil 2013-03-22 15:09:30

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).

1
répondu Some programmer dude 2011-11-03 09:42:57
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.

1
répondu Sorpigal 2011-11-03 12:59:11

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

0
répondu potong 2011-11-03 13:24:24

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;
0
répondu David Okwii 2013-11-13 19:55:12