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


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

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


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

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


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, это, безусловно, лучшее решение.



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

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будет возможность для этого.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.