Как составить список файлов в определенном порядке в соответствии с каталогом в Bash?

0

У меня есть куча каталогов, каждая из которых содержит кучу файлов. Обычно я могу перечислить все файлы с ls */*.* но это всегда перечисляет их в алфавитном порядке в каталогах, затем в алфавитном порядке в каждом каталоге Так что он всегда будет выводить

dir1 / file1.foo
dir1 / file2.foo
...
dir2 / file1.foo
dir2 / file2.foo
...
...
DIRN / file1.foo
DIRN / file2.foo
...

Вместо этого я хотел бы вывести его так, чтобы каталоги располагались в определенном порядке (например, в обратном порядке), но все файлы в каждом каталоге располагались в обычном порядке, например:

DIRN / file1.foo
DIRN / file2.foo
...
...
dir1 / file1.foo
dir1 / file2.foo
...

С помощью ls -r */*.* не делает то, что я хочу, потому что он меняет порядок внутри каждого каталога, а также порядок самих каталогов. Я пытался использовать ls `ls -r` который делает то, что я хочу для имен каталогов, в которых нет пробелов, но не работает для тех, которые делают (что, к сожалению, большинство из них) Если я попробую вместо ls "`ls -r`" затем выводит то же самое, что и ls -r - список имен каталогов, но в обратном порядке. Как заставить bash делать то, что я хочу?

Dee Ethier
источник

Ответы:

1

С использованием sort команда:

ls */* | sort -rst '/' -k1,1

с:

  • -t '/' изменить разделитель полей
  • -r сделать обратную сортировку
  • -s чтобы обеспечить стабильность сортировки (другими словами, она не меняет порядок за пределами указанных столбцов
  • -k1,1 ограничить сортировку первым столбцом

Это предполагает, что выход ls */* уже отсортировано (что и должно быть), в противном случае добавьте простой sort этап в середине.

xenoid
источник
0

через zsh скрипт

Как и в большинстве вещей в Linux / Unix, есть более одного способа сделать что-то. К счастью или круче, и ради чего это стоит, это еще один способ сделать то же самое.

#!/usr/bin/env zsh
Dirs=(*(/D))  # (/D) = /(only directories) D(include hidden or dot)
for D in ${(O)Dirs}  # (O) = reverse sort
do
    L=(${D}/*(ND))  # (ND) = N(in case the glob is empty) D(see above)
    [ ${#L} -eq 0 ] && { print "${D}/" ; continue }  # if empty glob
    print -l ${(o)L}  # (o) = normal sort
done

print Zsh встроенный -l выводит каждый элемент в отдельной строке.

Оставь в покое D Спецификатор glob, если вы не хотите выводить список скрытых каталогов и файлов.

Friartek
источник
0

Дополнение ответа @ xeniod (начинался как комментарий, но получался слишком длинным): согласно исходному требованию сортировки каталогов в обратном порядке и файлов в алфавитно-цифровом порядке

$ ls -d */* | sort -s -t '/' -k1,1rn -k2,2

Или, если файлы / каталоги имеют более одной цифры, например, вместо dir1..dir9у вас также есть dir10, dir11, dir101,... и файлы file1..file10..file101...Вы можете сортировать как "номера версий", используя опцию -V, против только буквенно-числовой сортировки (поддерживается только в сортировке GNU):

$ ls -d */* | sort -s -t '/' -k1,1rV -k2,2V

В идеале, однако, ваши каталоги & amp; файлы будут иметь специальные префиксные символы (или разделять) поля, по которым вы хотите отсортировать, как тире (" - "), например dir-23/file-1.txt, dir-902/file-203.txtи т. д., чтобы можно было сортировать только по этим полям (нечисловой текст после того, как число игнорируется):

$ ls -d */* | sort -s -t- -k2,2nr  -k3,3n

Ключевые моменты:

  • добавить несколько -k{begin,end} сортировать столбцы между разделителями / отдельно, например, сортируйте первый столбец как буквенно-цифровой, второй - как обратный-цифровой, третий - как «номера версий» и т. д.
  • Я добавил " -d "до" ls -d */* ", чтобы содержимое каталога не отображалось, что приведет к нарушению сортировки, если они существуют. только рассмотреть файлы, мог бы использовать find */ -maxdepth 1 -type f вместо ls.)
  • Обратите внимание, что вы действительно не заботитесь о «/» в своем роде, что обычно хорошо. Обратите внимание, вы не можете иметь более одного -t {delim} вариант в одном роде в любом случае (например, -t '-' -k... -t '/'... )
michael
источник