BASH: как зациклить все файлы в отсортированном порядке - PullRequest
43 голосов
/ 03 ноября 2011

Я зацикливаю все файлы в каталоге с помощью следующей команды:

for i in *.fas; do some_code; done;

Однако я получаю заказ следующим образом:

vvchr1.fas
vvchr10.fas
vvchr11.fas

вместо vvchr1.fas, vvchr2.fas, vvchr3.fas, что такое числовой порядок.

Я пробовал команду сортировки, но безуспешно.

Ответы [ 7 ]

82 голосов
/ 03 ноября 2011
for i in `ls *.fas | sort -V`; do some_code; done;

, где sort -V делает согласно man sort сортировку версий - естественный вид (версии) чисел в тексте

То же самое, используя только ls:

for i in `ls -v *.fas`; do echo $i; done;
4 голосов
/ 03 ноября 2011

Вы получите файлы в порядке ASCII. Это означает, что vvchr10* предшествует vvchr2*. Я понимаю, что вы не можете переименовать ваши файлы (мой мозг биоинформатика говорит мне, что они содержат данные о хромосоме, а мы просто не называем хромосому 1 "chr01"), поэтому вот другое решение (не использующее sort -V, которое я не могу найти в любой операционной системе, которую я использую):

ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/\1 \2/' | sort -k2,2n | tr -d ' ' |
while read filename; do
  # do work with $filename
done

Это немного запутанно и не будет работать с именами файлов, содержащими пробелы.

Другое решение. Предположим, что вместо этого мы хотим перебирать файлы в порядке размеров, что может быть более подходящим для некоторых задач биоинформатики:

du *.fas | sort -k2,2n |
while read filesize filename; do
  # do work with $filename
done

Чтобы отменить сортировку, просто добавьте r после -k2,2n (чтобы получить -k2,2nr).

3 голосов
/ 22 марта 2013

С опцией sort -g сравнивается по общему числовому значению

 for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done

0.log 1.log 2.log ... 10.log 11.log

Это будет работать только в том случае, если имена файлов являются числовыми. Если они строковые, вы получите их в алфавитном порядке. E.g.:

 for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done

сырец / 0.log сырья / 10.log сырья / 11.log ... сырье / 2.log

1 голос
/ 03 ноября 2011
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/ //;'

Решает проблему, предполагая, что имя файла остается согласованным, не полагается на самые последние версии GNU sort, не полагается на чтение вывода ls и не становится жертвой конвейера. проблемы на время.

1 голос
/ 03 ноября 2011

Вы имеете в виду, что файлы с номером 10 идут раньше файлов с номером 3 в вашем списке?Это потому, что ls сортирует результат очень просто, поэтому something-10.whatever на меньше , чем something-3.whatever.

Одним из решений является переименование всех файлов, чтобы они имели одинаковое количество цифр (файлы с одной цифрой начинаются с 0 в номере).

0 голосов
/ 13 ноября 2013

используйте sort -rh и цикл while

du -sh * | sort -rh | grep -P "avi$" |awk '{print $2}' | while read f; do fp=`pwd`/$f; echo $fp; done;
0 голосов
/ 03 ноября 2011

Как и решение @ Kusalananda (возможно, легче запомнить?), Но обслуживает все файлы (?):

array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/\1 &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done

По сути добавить ключ сортировки, сортировать, удалить ключ сортировки.

РЕДАКТИРОВАТЬ: переместить комментарий в соответствующее решение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...