Список файлов, отсортированных по номерам

123

У меня есть куча файлов от log1до log164.

Я пытаюсь перечислить каталог (отсортированный) в терминале UNIX, но функции сортировки предоставляют только такой формат:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Что я хочу это

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Любые предложения в том, что я мог бы использовать для этого?

Volker Siegel
источник
8
Это абсолютно программный вопрос, и его не стоит переносить только потому, что ответ включает в себя непритязательный язык программирования оболочки !!!
сентября
Если вы заранее знаете , что они называются log1.gzчерез log164.gz, то , что вы даже не нужно ls -1им для?
Руах
1
@ruakh ls -1 отображает результаты в одном столбце, а не поперек
3
@Rabiani: я знаю, что ls -1делает: в нем перечислены имена файлов. Поскольку вы уже знали имена файлов, я не понял, для чего вам это нужно. Но поскольку вы приняли ответ Кевина, теперь я знаю: он вам не нужен. Что имеет больше смысла. :-)
Руах

Ответы:

40

bashБрекеты, {}перечислю их по порядку:

for file in log{1..164}.gz; do
    process "$file"
done
Kevin
источник
267

Почему бы не использовать встроенную lsфункцию для этого конкретного случая, а именно

-v natural sort of (version) numbers within text

Например ls -1v log*

Лик
источник
Потрясающее решение, хотя я бы хотел, чтобы было такое же простое решение sort, если у вас есть массив строк, а не каталог файлов
Hubro
23
На BSD / OSX эта опция что - то другое: -v - Force unedited printing of non-graphic characters.
Кенорб
К сожалению, опция -v недоступна в AIX (6.1)
bouvierr
6
Это должен быть лучший ответ.
32r34wgf3e
1
для MacOS это будет работать, не могу найти опцию, как упомянуто, толькоls | sort -n
Рики Леви
47

С GNU ls (т.е. в Linux, Cygwin или других системах, в которых специально установлены GNU ls):

ls -v

В зш:

echo *(n)

В других оболочках:

echo log?.gz log??.gz log???.gz

Замените echoна, printf '%s\n'если вы хотите, чтобы каждое имя файла находилось в отдельной строке.

Если вам также нужны метаданные файла ( ls -l) и у вас нет GNU ls, вам нужно будет вызывать lsотдельно для каждого имени файла или группы имен файлов, которые вы хотите видеть в лексикографическом порядке.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Чтобы избежать этих трудностей, используйте достаточно начальных нулей в именах файлов, чтобы лексикографическая сортировка была удобной для человека ( log001.gzи т. Д.).

жилль
источник
29

Хотя решение ls -1v, безусловно, самое приятное в данном конкретном случае, я думаю, что было бы хорошо иметь такое, с которым можно работать, sortкак в первоначальном вопросе, поскольку оно работает и тогда, когда ваш вклад не приходит ls. В этом случае вы можете использовать:

ls -1 | sort -n -k1.4

-nОпция указывает сортировки для сортировки численно, и -k 1.4устанавливает ключ сортировки в первом поле (которое все имя файла в данном случае) , начиная с 4 - го символа до последнего.

Эльмар Цандер
источник
В моем случае ls -1 | sort -n -k1.4не работает. Он дает несортированным сначала до 4 символов, затем сортирует после 4-го символа. Я использовал ls -1 |sort | sort -n -k1.4вместо этого, и он работал отлично.
Прабху
3
@Прабху, вместо этого, ты мог бы сделать sort -k1.1,1.3 -k1.4n. sortреализации не обязательно должны быть стабильными, поэтому ваш подход не будет работать со всеми реализациями. Смотрите также -Vопцию GNU и FreeBSD sort.
Стефан Шазелас
21

GNU sort(как доступно в Linux) имеет режим «сортировки версий», который интерпретирует числа внутри не-чисел так, как вы просите:

От man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Создание пустых тестовых файлов в список:
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz)

Ваш пример случая, добавив -Vопцию (или --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz
Volker Siegel
источник
6

если вы используете Mac или BSD, попробуйте это:

ls -1 *.jpg | sort -n
Сальвадор Альмараз
источник
3

Моя версия Solaris не поддерживает ls -v(grrr). И решение для сортировки, представленное выше 1), требует знания позиции цифр в имени файла, и 2) не обрабатывает такие вещи, как номера версий из нескольких частей.

Подход, описанный ниже, совместим с Solaris, не требует предварительного знания позиций цифр и обрабатывает номера версий с 2, 3 или 4 компонентами (например: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Он также используется sort -fдля складывания прописных и строчных букв и правильно обрабатывает каталоги, смешанные с файлами:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Обратите внимание, что эта версия ограничивает первый компонент одной цифрой.

Если ваша целевая операционная система (ы) поддерживает ls -v, это, безусловно, лучшее решение.

MykennaC
источник
1

Perl решение:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
Бартон Читтенден
источник
1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
kjohri
источник
1
Здесь -t .лишнее.
Стефан Шазелас
0

Это сработало для меня.

У меня есть файлы 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortпутается с lsвыводом из-за непечатаемых цветных символов. Если вы попробуете это:

ls -1 --color=none *.jpg | sort -n

это будет работать отлично.

sortможет игнорировать непечатные символы с -iопцией, но она все еще не работает, и я не знаю почему.

Но вы всегда можете обрезать цвет следующим образом sort:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Я надеюсь, что однажды sortбудет возможность для этого.

cy8g3n
источник