Je boucle tous les fichiers du répertoire avec la commande suivante:
for i in *.fas; do some_code; done;
Cependant, je reçois ordre comme ceci:
vvchr1.fas
vvchr10.fas
vvchr11.fas
au lieu de vvchr1.fas, vvchr2.fas, vvchr3.fas, quel est l'ordre numérique.
J'ai essayé de trier la commande, mais sans succès.
for i in `ls *.fas | sort -V`; do some_code; done;
où sort -V
fait selon man sort
une sorte de version - une sorte naturelle de nombres (version) dans le texte
Le même en utilisant seulement 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 tout simplement pas le chromosome 1 "chr01"). Voici donc une autre solution (ne pas utiliser sort -V
que je ne trouve sur aucun système d'exploitation que j'utilise):
ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/\1 \2/' | sort -k2,2n | tr -d ' ' |
while read filename; do
# do work with $filename
done
Ceci est un peu compliqué et ne fonctionnera pas avec les noms de fichiers contenant des espaces.
Une autre solution: supposons que nous voulions parcourir les fichiers par ordre de taille, ce qui serait peut-être plus approprié pour certaines tâches de bioinformatique:
du *.fas | sort -k2,2n |
while read filesize filename; do
# do work with $filename
done
Pour inverser le tri, ajoutez simplement r
après -k2,2n
(pour obtenir -k2,2nr
).
Avec l'option sort -g il compare en fonction de la valeur numérique générale
for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done
0.log 1.log 2.log ... 10.log 11.log
Cela ne fonctionnera que si le nom des fichiers est numérique. S'ils sont ficelés, vous les obtiendrez dans l'ordre alphabétique. Par exemple.:
for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done
raw/0.log raw/10.log raw/11.log ... raw/2.log
while IFS= read -r file ; do
ls -l "$file" # or whatever
done < <(find . -name '*.fas' 2>/dev/null | sed -r -e 's/([0-9]+)/ \1/' | sort -k 2 -n | sed -e 's/ //;'
Résout le problème, en supposant que la dénomination des fichiers reste cohérente, ne repose pas sur des versions très récentes de GNU sort
, ne repose pas sur la lecture du résultat de ls
et ne soit pas victime de la filiation problèmes.
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 très simplement le résultat, donc something-10.whatever
est plus petit que something-3.whatever
.
Une solution consiste à renommer tous les fichiers pour qu'ils aient le même nombre de chiffres (les fichiers contenant un seul chiffre commencent par 0
dans le numéro).
Comme la solution de @ Kusalananda (peut-être plus facile à retenir?) Mais pour tous les fichiers (?):
array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/\1 &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done
Essentiellement, ajoutez une clé de tri, triez, supprimez la clé de tri.
EDIT: commentaire déplacé vers la solution appropriée
utiliser sort -rh et la boucle while
du -sh * | sort -rh | grep -P "avi$" |awk '{print $2}' | while read f; do fp=`pwd`/$f; echo $fp; done;