Как пакетно переименовать файлы в терминале macOS?

123

У меня есть папка с рядом файлов с именем:

prefix_1234_567.png
prefix_abcd_efg.png

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

prefix_567.png
prefix_efg.png

Актуально, но не полностью пояснительно:

kidnim
источник
посмотрите на методы диапазона и подстроки NSString и NSMutableString
Grady Player
1
Вы рассматривали нетерминальные решения для этого? Рабочий процесс Automator может легко выполнять эти типы операций. Вы можете создать рабочий процесс автомата, чтобы переименовать все файлы и заменить текст _*_пустым.
Encryptic
я думал, что автомат не может использовать подстановочные знаки
kidnim

Ответы:

234

В вашем конкретном случае вы можете использовать следующую bashкоманду ( bashэто оболочка по умолчанию в macOS):

for f in *.png; do echo mv "$f" "${f/_*_/_}"; done

Примечание. Если есть вероятность, что имена ваших файлов начинаются с -, поместите -- перед ними [1]:
mv -- "$f" "${f/_*_/_}"

Примечание: echoдобавляется перед mvтем, чтобы выполнить пробный прогон. Удалите его, чтобы выполнить фактическое переименование.

Вы можете запустить его из командной строки или использовать в сценарии.

  • "${f/_*_/_}"представляет собой приложение bash расширения параметра : (первая) подстрока, соответствующая шаблону _*_, заменяется литералом _, фактически вырезая средний токен из имени.
  • Обратите внимание, что _*_это шаблон (выражение с подстановочными знаками, которое также используется для подстановки), а не регулярное выражение (чтобы узнать о шаблонах, запустить man bashи найти Pattern Matching).

Если вы часто сталкиваетесь с переименованием файлов в пакетном режиме, подумайте об установке специального инструмента, такого как renameутилита на основе Perl . В macOS вы можете установить его с помощью популярного менеджера пакетов Homebrew следующим образом:

brew install rename

Вот эквивалент команды вверху с использованием rename:

rename -n -e 's/_.*_/_/'  *.png

Опять же, эта команда выполняет пробный прогон; удалить, -nчтобы выполнить фактическое переименование.

  • Аналогично bashрешению s/.../.../выполняет подстановку текста, но, в отличие от bashнастоящих , используются регулярные выражения .

[1] Назначение специального аргумента --, который поддерживается большинством утилит, состоит в том, чтобы сигнализировать, что последующие аргументы должны рассматриваться как операнды (значения), даже если они выглядят как опции из-за того, что они начинаются с -, как отмечает Джейкоб К.

mklement0
источник
3
отличный ответ, отлично работал. Я также ценю, что вы вернулись и отредактировали его, чтобы объяснить это подробнее и предоставить более элегантное решение, если я повторю это. еще раз большое спасибо, очень полезно
kidnim 08
4
Пример использования совпадающих замен ( .*-> $1), например Rename Foo bar S01E01 biz baz.extto S01E01.ext:rename -n -e 's/.*(S[0-9]{2}E[0-9]{2}).*(\.[a-z]{2,4})/$1$2/' *
Steve Robbins
2
Мне нравится идея использования echoдля сухих пробежек. Спасибо за чаевые!
Джеймс Райт
Настоятельно рекомендую просто сделатьbrew install rename
Крис Редфорд
98

Для переименования файлов можно использовать renameутилиту:

brew install rename

Например, чтобы изменить строку поиска во всех именах файлов в текущем каталоге:

rename -nvs searchword replaceword *

Удалите параметр «n», чтобы применить изменения.

Больше информации: man rename

Дэвид Томас
источник
1
OS Xверсии GNU bash( x86_64-apple-darwin ) не включают утилиту переименования.
l'L'l
4
Спасибо, да, это нужно установить с помощьюbrew install rename
Дэвида Томаса
2
Этот совет потрясающий! Я набрал, rename -vs GLYCOPHORIN GLYCC *и теперь он автоматически переименовывает 450+ файлов. И очень быстро.
Sander W. van der Laan,
3
Превосходно! Мне нравится часть «покажи, что было бы изменено», ДО того, как она действительно переименовывает вещи!
Ben Duffin
3
Вы также можете использовать регулярное выражение. переименовать 's / 123 / onetwothree / g' *
Брайан
12

Вы можете использовать sed:

ls * | sed -e 'p;s@_.*_@_@g' | xargs -n2 mv

результат:

prefix_567.png prefix_efg.png

* чтобы сначала выполнить пробный прогон, замените mvв конце наecho

Объяснение:

  • e: необязательно только для 1 команды sed.
  • p: для печати ввода в sed, в этом случае это будет исходное имя файла перед любым переименованием
  • @: заменяет символ /, чтобы сделать sed более читабельным. То есть вместо использования sed s / search / replace / g используйте s @ search @ replace @ g
  • _. *: подчеркивание - это escape-символ для обозначения фактического '.' символ ноль или более раз (в отличие от ЛЮБОГО символа в регулярном выражении)
  • -n2: указывает, что есть 2 выхода, которые необходимо передать в mv в качестве параметров. для каждого ввода от ls эта команда sed сгенерирует 2 вывода, которые затем будут переданы mv.
l'L'л
источник
1
Умное, хотя и несколько загадочное решение. Делая это более общим, чтобы также поддерживать имена файлов со встроенными пробелами, становится еще более загадочным: ls * | xargs -I % bash -c 'echo mv "%" "$(sed 's@_.*_@_@' <<<"%")"'(удалите, echoчтобы фактически переименовать).
mklement0 08
2
Arcane? Мне это нравится!
Билал Акил
7

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

for f in *; do mv "$f" "`echo $f | tr '-' '_'`"; done
JanB
источник
2

вы можете установить renameкоманду с помощью brew. просто делай brew install renameи пользуйся.

Нисим Джозеф
источник
1

С помощью mmv

mmv '*_*_*' '#1_#3' *.png
αғsнιη
источник
вам нужно сначала установить sudo apt-get install mmv.
αғsнιη
1
Учитывая, что это была OS X, правильная процедура установки brew install mmv.
buckaroo1177125
1

попробуй это

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

Вот еще один способ:

for file in Name*.png; do mv "$file" "01_$file"; done
Тьяго
источник