LINUX.ORG.RU

Отсортировать дерево файлов по расширению

 , , ,


0

2

Имеется сложная древовидная структура директорий с кучей файлов. Требуется вывести список файлов (без директорий, но это легко фильтруется по grep '/$' или find -type f) с полными путями, отсортированный по расширению. Очевидное решение

ls -X `find dirname -type f`
не работает из-за числа файлов:
$ find dirname | wc
  68974   70533 4281002
Все найденные в сети решения (с awk, tree...) сортируют только внутри отдельных директорий, а не глобально.

Можно получить список расширений при помощи

find dirname -type f | \
grep -o '.*\.[^/]*' | \
sed 's/^.*\.\([^\./]*\)$/\1/' | \
sed 'y/QWERTYUIOPASDFGHJKLZXCVBNM/qwertyuiopasdfghjklzxcvbnm/' | \
sort | \
uniq 
несколько сотен раз вызвать find для каждого и склеить. Но некрасиво.

Как ещё можно отсортировать? Или можно увеличить обрабатываемый ls объём?

Зачем это требуется? Хочу сравнить сжатие бэкапов новым 7z и новым RAR, а RAR сортирует по расширению. Подогнать список к порядку rarfiles.lst один раз можно и вручную, но сортировать вручную тысячи директорий неохота.

Заранее спасибо.

Ответ: Самое короткое решение:

find dirname -type f | rev | sort | rev
Помимо расширения группирует файлы с одинаковыми названиями.

Более длинные варианты выводят расширение в 1-ю колонку средствами perl или zsh. Или sed. Или awk.

Но попытка испытать 7z-15.09 провалилась. Он непонятным образом тасует список пользователя, и получился архив на треть длиннее, чем без сортированного списка.

★★★★★

Последнее исправление: question4 (всего исправлений: 4)

find . -type f -printf "%-20f\t%kKb\n"
find . -type f -printf "%TY%Tm%Td %s %p\n"

Не помню что здесь что обозначает, но суть думаю ясна.

sin_a ★★★★★
()
Ответ на: комментарий от sin_a

Нет, не ясна. Предложенные команды выводят различную информацию о файлах, но не позволяют вычленить расширение и не сортируют.

question4 ★★★★★
() автор топика

На zsh как-то так выглядит:

# Создаем файлы
mkdir -p 1 && mkdir -p 2 && touch 1/1.txt && touch 1/1.so && touch 2/2.txt && touch 2/2.so

# Печатаем
for i in $(find . -type f) ; do echo ${i:e} $i; done | sort 

Файлы

.
./1
./1/1.so
./1/1.txt
./2
./2/2.so
./2/2.txt

Вывод:

so ./1/1.so
so ./2/2.so
txt ./1/1.txt
txt ./2/2.txt
anonymous
()
Ответ на: комментарий от kostik87

ls -1 --sort=extension

Как заставить его вывести полный путь к файлу?

question4 ★★★★★
() автор топика

Если я правильно понял задачу,

$ find dirname -type f | perl -ne'push @data, [ $_, lc((/\.([^.]+)$/g)[0])||"" ]}{print map $_->[0], sort { $a->[1] cmp $b->[1] } @data'

AITap ★★★★★
()

Тоже на zsh:

% print -rl -- **/*(.oe%'REPLY="$REPLY:e"'%)
На 150k файлов вроде отработало.

salsa
()
Ответ на: комментарий от bl

Великолепно. Именно такое простое решение я и искал. Вдобавок, файлы с одинаковыми именами оказываются вместе.

question4 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.