Переименование файлов рекурсивно в sh

Я использую Synology для хранения фильмов с камер видеонаблюдения. После копирования файла из системы CCTV в Synology я конвертирую его в формат AVI. Итак, у моих файлов есть такие имена:

10.01.07-10.01.48[M][@0][0].dav.avi 

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

 10.01.07-10.01.48.avi 

Обратите внимание, что каждое имя файла состоит из одной и той же части [M][@0][0].dav.avi

Но проблема в том, что в оболочке Synology нет команды rename (это не будет bash )

Я пытался использовать команду find во многих разных синтаксисах, но безуспешно. Можете ли вы помочь мне найти решение?

  • Что означает двоеточие (':') в синтаксисе разрешения переменной bash?
  • Как просматривать файлы, имеющие разрешение на чтение только в моем рабочем каталоге?
  • Как найти файлы с тем же именем, но разные строки в двух каталогах?
  • проблема сценария оболочки с использованием операторов
  • Задача, не выполняемая crontab
  • * .desktop или symlink работает (только для этого одного файла) - Linux Mint 17.2 Cinnamon
  • Как привести текст HEREDOC в переменную сценария оболочки?
  • Как открыть терминал, разделить на 9 терминалов и переключиться между ними, используя один скрипт?
  • 4 Solutions collect form web for “Переименование файлов рекурсивно в sh”

    Вы можете сделать:

     find . -name '*\[M]\[@0]\[0].dav.avi' -type f -exec sh -c ' for file do echo mv "$file" "${file%"[M][@0][0].dav.avi"}.avi" done' sh {} + 

    (удалите echo если все будет хорошо).

    Или если вы хотите переименовать все .dav.avi в .avi , но также удалить [M][@0][0] если есть:

     find . -name '*.dav.avi' -type f -exec sh -c ' for file do new=${file%.*.*} new=${new%"[M][@0][0]"}.avi echo mv "$file" "$new" done' sh + 

    Это синтаксис POSIX, а также работа с утилитами busybox, поэтому он должен работать на синологии.

    Несколько заметок (основанных на наблюдениях ваших собственных и других ответов):

    • шаблон, переданный в find -name должен быть процитирован, иначе он может быть расширен оболочкой.
    • вы не можете использовать xargs для имен файлов, если вы не можете гарантировать, что эти имена файлов не будут содержать пробелы или символы новой строки или кавычки или обратную косую черту.
    • Используйте printf вместо echo для вывода произвольных данных .
    • Оставляя переменное расширение без кавычек в контексте списка, имеет особое значение . Вы не хотите делать это здесь.
    • . character является специальным оператором регулярного выражения, вам нужно избегать его в регулярных выражениях, если вы хотите, чтобы его обрабатывали буквально.
    • Синтаксис для чтения строки с read – это строка IFS= read -r line , но опять же нет гарантии, что путь к файлу будет состоять только из одной строки.
    • Часто бывает лучше делать (cd -P -- "$dir" && find . ... -exec) чем find -- "$dir" ... -exec потому что он избегает проблем с значениями $dir которые оказываются find предикаты или начинаются с - и потому, что он сокращает путь к файлу, переданный в -exec и, таким образом, позволяет передавать больше.

    Вот быстрое решение, использующее sed для переименования файлов:

     echo "10.01.07-10.01.48[M][@0][0].dav.avi" | sed 's/\[.*dav//' 10.01.07-10.01.48.avi 

    Я ничего не знаю об оболочке Synology, но надеюсь, что sed доступен!

    Используйте (например) в цикле:

     #!/bin/sh for file in *avi; do newName=$(echo "$file" | sed 's/\[.*dav//') mv -v "$file" "$newName" done 

    До:

     ls 09.01.07-13.11.48[M][@0][0].dav.avi 110.01.07-13.11.48[M][@0][0].dav.avi 12.01.07-13.11.48[M][@0][0].dav.avi 

    Запуск скрипта:

     ./renameAvi.sh ”09.01.07-13.11.48[M][@0][0].dav.avi” -> ”09.01.07-13.11.48.avi” ”110.01.07-13.11.48[M][@0][0].dav.avi” -> ”110.01.07-13.11.48.avi” ”12.01.07-13.11.48[M][@0][0].dav.avi” -> ”12.01.07-13.11.48.avi” 

    После:

     ls 09.01.07-13.11.48.avi 12.01.07-13.11.48.avi 110.01.07-13.11.48.avi 

    Изменить: если вы хотите использовать find один из способов реализации – это как в этом oneliner:

     find . -name "*.avi" | while read fileName; do newName=$(echo "$fileName" | sed 's/\[.*dav//'); mv -v "$fileName" "$newName"; done ”./01.01.07-13.11.38[M][@0][0].dav.avi” -> ”./01.01.07-13.11.38.avi” ”./01.01.07-13.11.39[M][@0][0].dav.avi” -> ”./01.01.07-13.11.39.avi” 

     sed --version sed (GNU sed) 4.2.2 find --version find (GNU findutils) 4.4.2 

    Для переименования рекурсивных файлов вы должны использовать команду ниже.

     find . -name "*dav.avi" | while read fileName; do newName=$(echo "$fileName" | sed 's/\[.*dav//'); mv -v "$fileName" "$newName"; done 

    Измените сценарий выше

    (Я не мог добавить комментарий выше, поэтому добавление ответа здесь с небольшим изменением в скрипте, о котором уже говорилось в maulinglawns)

    • Используйте для поиска * dav.avi, так как у вас будет много рекурсивных файлов в вашем хранилище Synology, поэтому, как только эти файлы будут переименованы, это должно быть сделано снова.
    • Это очень небольшое изменение, но будет действовать, если ваша фактическая система ~ GBs файлов данных.

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

     find $katalog -type f -name *.dav.avi | sed -e "p;s/.dav.avi/\.avi/" | xargs -n2 mv 2>/dev/null find $katalog -type f -name *.avi | sed -e "p;s/\[M\]\[@0\]\[0\].avi/\.avi/" | xargs -n2 mv 2>/dev/null 
    Interesting Posts

    Как заблокировать определенный URL-адрес на маршрутизаторе DD-WRT?

    Не удалось получить беспроводные драйверы Broadcom, работающие в Arch Linux

    Почему scp не показывает истинную скорость загрузки?

    как освободить / dev / ram0

    Есть ли разница между «привилегиями root root» и «выполнить любую команду»?

    Команда Spawn не найдена

    Как я могу прочитать жесткий диск Linux из Windows?

    Grub не загружается с GPT RAID (отказался от ожидания корневого устройства)

    lm-sensor, как правильно установить / вычислить только минимальные / максимальные значения для чтения?

    Что это означает от xev?

    как я могу изменить то, что ищет команда «apt-get update» при выполнении обновления?

    Как настроить цвета приложений Qt в Ubuntu (16.10)?

    Как обрабатывать недоступные пакеты texlive на el7

    Как напечатать переменную bash, которая имеет массив как значение

    Как настроить две письма для двух разных пользователей в Ubuntu

    Linux и Unix - лучшая ОС в мире.