11

Я искал способ переименовать огромное количество файлов с одинаковыми именами, очень похоже на этот (вопрос, связанный с Windows), за исключением того, что я использую * nix (Ubuntu и FreeBSD, отдельно). Чтобы подвести итог, при использовании оболочки (Bash, CSH и т.д.), Как мне массово переименовать несколько файлов, например, следующие файлы:

Бетховен - Мех Elise.mp3
Бетховен - Лунная соната.mp3
Бетховен - Ода радости.mp3
Бетховен - Ярость над потерянным Penny.mp3

будут переименованы как эти?

Мех Elise.mp3
Moonlight Sonata.mp3
Ода Joy.mp3
Rage Over the Lost Penny.mp3

Причина, по которой я хочу сделать это, состоит в том, что эта коллекция файлов будет находиться в каталоге с именем "Бетховен" (то есть префикс имени файла), и наличие этой информации в самом имени файла будет избыточным.

9 ответов9

12

Утилита переименования сделает то, что вы хотите.

Просто используйте rename 's/Beethoven\ -\ //g' *.mp3

10

Подобно многим вещам в Linux/Unix, существует несколько способов сделать это!

Некоторые могут использовать mmv (масса mv).

Команда rename или prename, поставляемая с некоторыми пакетами Perl (более новыми Ubuntu и Debian), также может это делать.

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

Обратите внимание, что инструмент переименования в Fedora 10 не та же программа, что и эта, и работает по-другому. Он является частью другого пакета util-linux-ng и может быть найден здесь.

Я часто просто захожу в оболочку по привычке (ведь таких инструментов не всегда было).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Это создаст каталог Бетховена, затем переместит файл в этот каталог / имя файла, где имя файла заменено на «Бетховен -» ничем.

В качестве теста, прежде чем:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

После:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3
4

Попробуйте это решение, реализованное с использованием комбинации grep и rename. Это предполагает, что у вас есть целая куча каталогов, которые вам нужно переименовать. Если бы их было всего несколько, я бы использовал ручной подход, с шаблоном «Artist -», жестко закодированным для каждого.

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Объяснение находки:
Команда find находит все файлы с расширением .mp3 в текущей файловой иерархии и вызывает аргумент, передаваемый -exec для каждого. Обратите внимание, что в -exec {} относится к аргументу, переданному командой find (путь к файлу + имя). \; обеспечивает ; передается для переименования и вместо указания конца команды поиска .

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

Теперь для регулярного выражения.

  • ^ соответствует началу строки.
  • $ соответствует концу строки.
  • . соответствует любому персонажу.
  • * означает ноль или более предшествующей конструкции. например .* означает ноль или более символов.
  • \s обозначает любой символ пробела.
  • \S обозначает любой непробельный символ.
  • Все, что находится внутри () захватывается и отображается как $1 , $2 , в зависимости от его положения.

Регулярное выражение:

  • В начале ищет необязательную структуру каталогов, фиксирует это в $ 1: (.*/)
  • Пропускает все , пока -
  • Захватывает остальную часть строки, исключая начальные и конечные пробелы, в $ 2: (.*)
  • Перезаписывает файл как $ 1 $ 2, который должен быть "/path/to/file/""filename.mp3"

Вот мой тестовый прогон:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

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

1

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

RenameWand
http://renamewand.sourceforge.net/

Некоторые соответствующие примеры использования:

Переместите файлы вида "<a> - <b>" в соответствующий каталог "<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

Сортируйте файлы по времени последнего изменения и переименуйте их по 3-значному номеру:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Переставьте части имени файла и измените регистр:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"
1

zmv Инструмент переименования zsh очень хорош.

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

Больше заметок здесь ...

0

Для пингвинов это легко сделать с помощью сценария оболочки или сценария AWK. Для нас, простых смертных, вы можете попробовать Midnight Commander. Это в большинстве дистрибутивов Linux, из командной строки введите mc -a. Вы можете переименовывать файлы, используя регулярные выражения. Я использовал статью в GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/, чтобы помочь мне.

0

На * nix без rename perl доступно

В некоторых * nix переименование недоступно, поэтому необходимо выполнить переименование другим способом. Несколько лет назад я предложил здесь использовать zmv который хотя и великолепен, но и не всегда доступен.

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

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

использование

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Скажем, мы тоже хотели создать целевые папки ...

Поскольку mv не создает папки, мы не можем использовать sedrename как здесь, но это довольно небольшое изменение, поэтому я думаю, что было бы неплохо включить его тоже.

Нам нужна служебная функция abspath (или абсолютный путь), чтобы мы могли сгенерировать целевую папку (и) для шаблона sed/rename, который включает новую структуру папок.

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

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

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

Вот полный сценарий с поддержкой папок ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Конечно, это все еще работает, когда у нас нет определенных целевых папок.

Если мы хотим , чтобы поставить все песни в ./Beethoven/ мы можем сделать это:

использование

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

Бонус раунд ...

Используя этот скрипт для перемещения файлов из папок в одну папку:

Предполагая, что мы хотим собрать все совпадающие файлы и поместить их в текущую папку, мы можем сделать это:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Обратите внимание на шаблоны регулярных выражений

В этом сценарии применяются правила регулярных шаблонов sed, эти шаблоны не являются PCRE (регулярные выражения, совместимые с Perl). Вы могли бы использовать расширенный синтаксис регулярного выражения sed, используя sed -r или sed -E зависимости от вашей платформы.

Смотрите POSIX-совместимый man re_format для полного описания основных и расширенных шаблонов регулярных выражений.

0

Используйте vidir, а затем используйте функции редактора, чтобы применить шаблон переименования.

НАЗВАНИЕ

vidir - редактировать каталог

СИНТАКСИС

vidir [--verbose] [каталог | файл | -] ...

ОПИСАНИЕ

vidir позволяет редактировать содержимое каталога в текстовом редакторе. Если каталог не указан, текущий каталог редактируется.

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

Обратите внимание, что если в качестве каталога для редактирования указано «-», он читает список имен файлов из stdin и отображает их для редактирования. В качестве альтернативы, список файлов может быть указан в командной строке.

ПРИМЕРЫ

vidir vidir * .jpeg Типичное использование.

найти | vidir - Редактировать содержимое подкаталога тоже. Чтобы удалить подкаталоги, удалите все их содержимое и сам подкаталог в редакторе.

найти -тип f | vidir - редактировать все файлы в текущем каталоге и подкаталогах.

АВТОР

Джои Хесс 2006-2010

Модификации Магнуса Волдриха 2011

АВТОРСКОЕ ПРАВО

Copyright 2006-2011 Vidir "АВТОР", как указано выше.

Лицензия под лицензией GNU GPL.

0

Вот простой пример командной строки. У меня было слово "белый" в середине названия группы файлов PNG. Я хотел вынуть это и оставить только одно подчеркивание. Это сделало трюк:

for i in *.png; do mv "$i" "${i/white/}"; done

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