3

Как отсортировать файлы или каталоги по части их имени, в частности по элементу, содержащемуся в скобках или разделенному разделителем?

Мне нужны два отдельных решения, одно для каталогов с именами, структурированными так:

Badger Bodger (2001)
Charlie Fisher's (1989)

И файлы в следующем формате:

Could Be A Title.2001.prop.ext1
Another Potential Title.1989.prop.ext2

В обоих случаях каталоги или файлы с 1989 года должны поступить до 2001 года. Для каталогов элемент для сортировки находится в скобках. Для файлов это первые четыре цифры после разделителя . ,

Я использую bash на Debian 8.0. Ищите решения командной строки, пожалуйста. Короткие сценарии, если они написаны на bash, приемлемы.

2 ответа2

1

Рассмотрим эти файлы:

$ ls  --quoting-style=c -1 *.*
"Another Potential Title.1989.prop.ext2"
"being there.2000.prop.ext3"
"Could Be A Title.2001.prop.ext1"
"Yet Another Potential Title.1989.prop.ext2"

Это сортирует по году:

$ ls  --quoting-style=c *.* | sort -t. -k2n
"Another Potential Title.1989.prop.ext2"
"Yet Another Potential Title.1989.prop.ext2"
"being there.2000.prop.ext3"
"Could Be A Title.2001.prop.ext1"

Для ваших каталогов аналогичный подход работает:

$ ls --quoting-style=c -d */ | sort -t'(' -k2n
"Charlie Fisher's (1989)/"
"Badger Bodger (2001)/"

Из-за опции --quoting-style=c этот подход будет работать даже с именами файлов с символами новой строки или другими сложными символами. Если вы уверены, что имена ваших файлов не содержат символов новой строки, вы можете опустить эту опцию.

Как это устроено

sort может разбить входные строки на поля. Опция -t устанавливает разделитель полей. Для файлов разделителем полей является . в то время как для каталогов используется разделитель полей ( . Опция -k определяет, какое поле сортируется. Для обоих указанных выше случаях мы просим sort сортировать численно на втором поле.

1

Я предполагаю, что вы уверены, что ни одно из ваших имен файлов не содержит символов новой строки или что у вас есть какой-то способ справиться с этой возможностью.  Во-первых, управляйте именами файлов с помощью sed:

% command_to_list_filenames | sed 's/.*\.\([0-9][0-9][0-9][0-9]\)\..*/\1.&/'
2001.Could Be A Title.2001.prop.ext1
1989.Another Potential Title.1989.prop.ext2
%

Команда s (заменитель) в команде sed обрабатывает каждую строку как последовательность следующего:

  • Любое число любого символа (.*),
  • Фактический период (\.),
  • Четыре цифры ([0-9][0-9][0-9][0-9]),
  • Еще один фактический период (\.) И
  • Другая последовательность символов (.*)

Обратите внимание, что год ([0-9][0-9][0-9][0-9]) заключен между \( и \) , образуя группу.  Затем команда замены заменяет строку на

  • Сгруппированные символы, т. Е. Год (\1),
  • Точка (.) И
  • Вся строка ввода (&).

Тогда нужно просто отсортировать строки по году (который теперь появляется в начале строки) и удалить год:

% command_to_list_filenames | sed 's/.*\.\([0-9][0-9][0-9][0-9]\)\..*/\1.&/' | sort
1989.Another Potential Title.1989.prop.ext2
2001.Could Be A Title.2001.prop.ext1
% command_to_list_filenames | sed 's/.*\.\([0-9][0-9][0-9][0-9]\)\..*/\1.&/' | sort |
                                                            sed 's/^[0-9][0-9][0-9][0-9].//'
Another Potential Title.1989.prop.ext2
Could Be A Title.2001.prop.ext1
%

Команда sed может быть тривиально изменена для обработки другого шаблона.  И sed может принимать входные данные из файла вместо канала:

% sed 's/.*(\([0-9][0-9][0-9][0-9]\)).*/\1.&/' list_of_directory_names | sort |
                                                            sed 's/^[0-9][0-9][0-9][0-9].//'
Charlie Fisher's (1989)
Badger Bodger (2001)
%

Обратите внимание, что это прекрасно работает с текстом, который содержит точки или скобки, например,

Dr. Strangelove.1964.foo
Mrs. Doubtfire.1993.bar

до тех пор, пока за ними не следуют четырехзначные числа.

Вы можете оставить второй .* Если хотите:

% command_to_list_filenames | sed 's/.*\.\([0-9][0-9][0-9][0-9]\)\./\1.&/'
2001.Could Be A Title.2001.prop.ext1
1989.Another Potential Title.1989.prop.ext2
%

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .