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


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.