Поиск по сайту:

Как массово переименовывать файлы в числовые имена файлов в Linux


Хотите переименовать целый набор файлов в числовую последовательность (1.pdf, 2.pdf, 3.pdf, …) в Linux? Это можно сделать с помощью небольшого скрипта, и эта статья покажет вам, как именно это сделать.

Числовые имена файлов

Обычно, когда мы сканируем файл PDF с помощью какого-либо оборудования (мобильного телефона, специального сканера PDF), имя файла выглядит примерно так: 2020_11_28_13_43_00.pdf. Многие другие полуавтоматические системы создают аналогичные имена файлов на основе даты и времени.

Иногда файл может также содержать название используемого приложения или некоторую другую информацию, такую как, например, применимое значение DPI (количество точек на дюйм) или размер отсканированной бумаги.

При объединении PDF-файлов из разных источников соглашения об именах файлов могут значительно различаться, и может быть целесообразно стандартизировать числовое (или частично числовое) имя файла.

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

Массовое переименование файлов в числовые имена файлов

В Linux легко быстро переименовать целый набор файлов с совершенно разными именами файлов в числовую последовательность. «Легко» здесь означает «легко выполнить»: проблема массового переименования файлов в числовые числа сложна для написания кода сама по себе: приведенный ниже скрипт oneliner занял 3-4 часа, чтобы исследовать, создать и протестировать. Многие другие испробованные команды имели ограничения, которых я хотел избежать.

Обратите внимание, что никаких гарантий не дается и не предоставляется, и этот код предоставляется «как есть». Пожалуйста, проведите собственное исследование, прежде чем запускать его. Тем не менее, я успешно протестировал его на файлах с различными специальными символами, а также на более чем 50 000 файлов без потери файлов. Я также проверил файл с именем a$na.pdf, который содержит новую строку.

if [ ! -r _e -a ! -r _c ]; then echo 'pdf' > _e; echo 1 > _c ;find . -name "*.$(cat _e)" -print0 | xargs -0 -I{} bash -c 'mv -n "{}" $(cat _c).$(cat _e);echo $[ $(cat _c) + 1 ] > _c'; rm -f _e _c; fi

Давайте сначала посмотрим, как это работает, а затем проанализируем команду. У нас есть созданный каталог с восемью файлами, названными совершенно по-разному, за исключением того, что их расширение совпадает и является .pdf. Затем мы запускаем команду выше:

В результате 8 файлов были переименованы в 1.pdf, 2.pdf, 3.pdf и т. д., несмотря на то, что раньше их имена были сильно смещены.

Команда предполагает, что у вас еще нет именованных файлов от 1.pdf до x.pdf. Если вы это сделаете, вы можете переместить эти файлы в отдельный каталог, установить echo 1 на более высокое число, чтобы начать переименование оставшихся файлов с заданным смещением, а затем снова объединить два каталога вместе.

Пожалуйста, всегда следите за тем, чтобы не перезаписать какие-либо файлы, и всегда полезно сделать быструю резервную копию, прежде чем что-либо обновлять.

Рассмотрим команду подробнее. Это может помочь увидеть, что происходит, добавив параметр -t в xargs, который позволяет нам увидеть, что происходит за кулисами:

Для начала команда использует два небольших временных файла (с именами _e и _c) в качестве временного хранилища. В начале однострочника выполняется проверка безопасности с помощью оператора if, чтобы убедиться, что и _e, и _c файлы отсутствуют. Если есть файл с таким именем, скрипт не будет работать.

Что касается темы использования небольших временных файлов по сравнению с переменными, я могу сказать, что, хотя использование переменных было бы идеальным (экономит часть дискового ввода-вывода), я столкнулся с двумя проблемами.

Первый заключается в том, что если вы ЭКСПОРТИРУЕТЕ переменную в начале oneliner, а затем используете эту же переменную позже, если другой скрипт использует ту же переменную (включая этот скрипт, запущенный более одного раза одновременно на одном компьютере), то этот скрипт, или этот, может быть затронут. Такого вмешательства лучше избегать, когда речь идет о переименовании большого количества файлов!

Во-вторых, xargs в сочетании с bash -c, по-видимому, имеет ограничение на обработку переменных внутри командной строки bash -c. Даже обширные онлайн-исследования не дали действенного решения для этого. Таким образом, в итоге я использовал небольшой файл _c, в котором сохраняется прогресс.

_e — это расширение, которое мы будем искать и использовать, а _c — это счетчик, который будет автоматически увеличиваться при каждом переименовании. Код echo $[ $ (cat _c) + 1 ] > _c позаботится об этом, отображая файл с cat, добавляя одно число и повторно писать это.

Команда также использует наилучший метод обработки специальных символов имени файла, используя нулевое завершение вместо стандартного завершения новой строки, т. е. символа . Это обеспечивается опцией -print0 для find и опцией -0 для xargs.

Команда find будет искать любые файлы с расширением, указанным в файле _e (созданном командой echo pdf > _e. Вы можете изменить это расширение на любое другое расширение хотите, но не ставьте перед ним точку. Точка уже включена в более поздний спецификатор *.$ (cat _e) -name для найти.

Как только find найдет все файлы и отправит их — завершится в xargs, xargs переименует файлы один за другим, используя файл счетчика (< i>_c) и тот же файл расширения (_e). Чтобы получить содержимое двух файлов, используется простая команда cat, выполняемая из подоболочки.

Команда перемещения mv использует -n, чтобы избежать перезаписи любого уже существующего файла. Наконец, мы очищаем два временных файла, удаляя их.

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

В Интернете есть множество других решений этой же проблемы, и многие пытались и не смогли создать полностью работающее решение. Многие решения забыли о всевозможных побочных случаях, таких как использование ls без указания --color=never, что может привести к анализу шестнадцатеричных кодов, когда используется цветовое кодирование списка каталогов. использовал.

Тем не менее, в других решениях отсутствует правильная обработка файлов с пробелами, символами новой строки и специальными символами, такими как «. Для этого используется комбинация find... -print0... | xargs -0 ... обычно указывается и является идеальным (и руководства find и xargs довольно сильно намекают на этот факт).

Хотя я не считаю свою реализацию идеальным или конечным решением, мне кажется, что она существенно улучшает многие другие решения, используя завершающие строки find и , обеспечение максимальной совместимости имени файла и синтаксического анализа, а также наличие нескольких других тонкостей, таких как возможность указать начальное смещение и полная нативность Bash .

Наслаждайтесь!