Как отсортировать результаты поиска (включая вложенные каталоги) по алфавиту в bash

У меня есть список каталогов, основанный на результатах выполнения команды "найти" в bash. Как пример, результатом поиска являются файлы:

test/a/file
test/b/file
test/file
test/z/file

Я хочу отсортировать вывод, чтобы он выглядел так:

test/file
test/a/file
test/b/file
test/z/file

Есть ли способ отсортировать результаты в команде поиска или передать результаты в сортировку?

4 ответа

Решение

Если у вас есть версия find для GNU, попробуйте это:

find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F '\0' '{print $3}'

Чтобы использовать эти имена файлов в цикле, выполните

find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F '\0' '{print $3}' | while read file; do
    # use $file
done

Команда find печатает три вещи для каждого файла: (1) его каталог, (2) его глубину в дереве каталогов и (3) его полное имя. Включая глубину в выводе, мы можем использовать sort -n Сортировать test/file выше test/a/file, Наконец мы используем awk вырезать первые два столбца, так как они использовались только для сортировки.

С помощью \0 разделитель между тремя полями позволяет нам обрабатывать имена файлов с пробелами и табуляцией в них (но, к сожалению, не переводы строк).

$ find test -type f
test/b/file
test/a/file
test/file
test/z/file
$ find test -type f -printf '%h\0%d\0%p\n' | sort -t '\0' -n | awk -F'\0' '{print $3}'
test/file
test/a/file
test/b/file
test/z/file

Если вы не можете изменить find команда, затем попробуйте эту запутанную замену:

find test -type f | while read file; do
    printf '%s\0%s\0%s\n' "${file%/*}" "$(tr -dc / <<< "$file")" "$file"
done | sort -t '\0' | awk -F'\0' '{print $3}'

Это делает то же самое, с ${file%/*} используется для получения имени каталога файла и tr команда, используемая для подсчета количества слешей, что эквивалентно "глубине" файла.

(Я очень надеюсь, что есть более простой ответ. То, что вы спрашиваете, не кажется таким уж сложным, но я отказываюсь от простого решения.)

      find test -type f -printf '%h\0%p\n' | sort | awk -F'\0' '{print $2}'

Результат find это, например,

      test/a'\0'test/a/file
test'\0'test/file
test/z'\0'test/z/file
test/b'\0'test/b/text file.txt
test/b'\0'test/b/file

куда '\0' обозначает нулевой символ.

Эти составные строки можно правильно отсортировать с помощью простого sort:

      test'\0'test/file
test/a'\0'test/a/file
test/b'\0'test/b/file
test/b'\0'test/b/text file.txt
test/z'\0'test/z/file

И конечный результат

      test/file
test/a/file
test/b/file
test/b/text file.txt
test/z/file

(На основе ответа Джона Кугельмана с удаленным элементом «глубина», что является абсолютно избыточным.)

Если вы хотите сортировать по алфавиту, лучший способ это:

find test -print0 | sort -z

(Пример в оригинальном вопросе на самом деле хотел файлы перед каталогами, что не то же самое и требует дополнительных шагов)

Попробуй это. для справки, он производит сортировку на втором поле второго символа. который существует только в файле и имеет ar для обратного значения, то есть он первый, после этого он будет сортироваться по первому символу второго поля. [-t это разделитель полей, -k это ключ]

find test -name file |sort -t'/' -k2.2r -k2.1

сделать info sort для получения дополнительной информации. Существует множество способов использовать -t и -k вместе, чтобы получить разные результаты.

Другие вопросы по тегам