Список файлів, відсортованих за числовим числом


122

У мене є купа файлів від 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
Це абсолютно програмне запитання, і воно не заслуговує на міграцію лише тому, що відповідь включає низькомовну мову програмування !!!
tchrist

Якщо ви знаєте заздалегідь, що вони названі log1.gzчерез log164.gz, то для чого вони вам навіть потрібні ls -1?
ruakh

1
@ruakh ls -1 відображає результати в одному стовпчику, а не впоперек

3
@Rabiani: Я знаю, що ls -1робить: у ньому перелічені імена файлів. Оскільки ви вже знали імена файлів, я не розумів, для чого вам це потрібно. Але оскільки ви прийняли відповідь Кевіна, я тепер знаю: вона вам не потрібна. Що має більше сенсу. :-)
ruakh

Відповіді:


40

bashдужки, {}перерахують їх у порядку:

for file in log{1..164}.gz; do
    process "$file"
done

266

Чому б не використовувати вбудовану 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.
kenorb

На жаль, опція -v недоступна на AIX (6.1)
bouvierr

6
Це має бути найкращою відповіддю.
32r34wgf3e

1
для MacOS це спрацює, не вдалося знайти варіант, як згадувалося,ls | sort -n
Рікі Леві,

47

Із GNU ls (тобто в Linux, Cygwin або інших системах, на яких спеціально встановлені GNU ls):

ls -v

В zsh:

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
@Prabhu, замість цього, ви могли б зробити 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(гррр). І рішення сортування, яке надано вище 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

Розчин Perl:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'


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.