Как заменить один символ другим во всех именах файлов текущих каталогов?

41

Как переименовать все файлы / подкаталоги в текущей папке?

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

File 1
File 2
File 3
Dir 1
Dir 3

следует переименовать в

File_1
File_2
File_3
Dir_1
Dir_3
NobbZ
источник

Ответы:

36

Если вам нужно переименовать файлы и в подкаталогах, и вы findподдерживаете -execdirпредикат, то вы можете сделать

find /search/path -depth -name '* *' \
    -execdir bash -c 'mv -- "$1" "${1// /_}"' bash {} \;

Спасибо @glenn Jackman за предложенный -depthвариант findи заставил меня задуматься.

Обратите внимание, что в некоторых системах (включая GNU / Linux) findможет не найти файлы, имя которых содержит пробелы, а также последовательности байтов, которые не образуют допустимые символы (обычно для файлов мультимедиа с именами, отличными от символов ASCII, закодированных в кодировке). отличается от локали). Установка локали C(как в LC_ALL=C find...) решит проблему.

enzotib
источник
Вам нужно было бы использовать find -maxdepth 1именно то, что ОП спросил о работе с текущей папкой.
Калеб
1
Используйте параметр поиска -depth, и вы можете избавиться от sort.
Гленн Джекман
@glenn Jackman: спасибо, теперь я понимаю, что мое решение было неверным.
энзотиб
2
Изменить -name '* *'на -name '*_*'и изменить "${1// /_}"на"${1//_/.}"
enzotib
1
@kroiz: это называется «Замена шаблона». Вы можете найти это в bashсправочной странице.
энзотиб
34

В любой оболочке вы можете перебирать файлы, имя которых содержит пробел. Заменить пробелы подчеркиванием легко в bash, ksh и zsh с помощью ${VARIABLE//PATTERN/REPLACEMENT}конструкции.

for x in *" "*; do
  mv -- "$x" "${x// /_}"
done

В Debian, Ubuntu и его производных вы можете использовать Perl rename(другие дистрибутивы поставляются с другой программой rename, и эта программа здесь не нужна).

rename 's/ /_/g' *

Обязательное зш решение:

autoload zmv
zmv '(*)' '${1// /_}'

Обязательное решение POSIX:

for x in *" "*; do
  y=$(printf %sa "$x" | tr " " "_")
  mv -- "$x" "${y%a}"
done
Жиль "ТАК - перестань быть злым"
источник
Что означает «g» в конце команды «переименовать»? Я не видел это в руководстве.
JulianLai
Как переименовать только каталог? Я не хочу менять имя файла.
JulianLai
@JulianLai s/…/…/gозначает заменить все вхождения. Это не очень хорошо объяснено в руководстве . Если вы хотите переименовать каталоги, есть способы, пожалуйста, найдите их (кажется, я видел это раньше) и, если вы не можете найти их, задайте новый вопрос.
Жиль "ТАК - прекрати быть злым"
здорово ... это помогло мне переименовать все _MG_blah.JPGв IMG_blah.JPG.
Абинаш Даш
13

Вы можете использовать renameдля этого (здесь предполагается, что один из util-linux, а не perlодин):

cd /path/to/dir
rename ' ' _ *\ *

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

Если вы хотите сделать рекурсивные соответствия, вы можете, но вам, возможно, придется выполнить renameпару раз, чтобы перехватить любые элементы в каталогах, которые сами были переименованы:

cd /path/to/dir
shopt -s globstar
rename ' ' _ **/*\ *
!!; !!
Калеб
источник
2
« renameПереименует указанные файлы, заменив первое вхождение from в их имени на to» . Таким образом, это будет работать только для файлов с одним пробелом в имени. (Вы можете позвонить renameв цикле, но это не совсем правильный инструмент здесь.)
Жиль: «Так, перестань быть злым»
2

Другой вариант будет mmv, если установлен.

mmv \*\ \* \#1_#2
glglgl
источник
Это только изменяет первый пробел на a _, он не работает с именами с несколькими пробелами.
Жиль "ТАК ... перестать быть злым"
Ой, ты прав. Извините за путаницу.
glglgl
1

В Debian / Ubuntu, опираясь на ответы Калеба и Жиля, я рекурсивно переименовал файлы:

cd /path/to/dir
shopt -s globstar
rename 's/ /_/g' **

Примечание. Чтобы просмотреть, какие файлы будут переименованы и как, используйте -nпереключатель с rename:

rename -n 's/ /_/g' **

Еще одно примечание: настройка globstarпозволяет **сопоставлять файлы во всех подкаталогах, поэтому, если требуется только текущий каталог, не устанавливайте globstar или используйте *вместо **.

Еще одно примечание: renameкоманду необходимо запускать более одного раза для файлов с несколькими вхождениями поискового запроса.

Маркус Пшайдт
источник
Это работает, только если каталоги не содержат пробелов. (переименование a b/c dв a_b/c_dне сработает, сначала нужно переименовать a b/c dв a b/c_d, а затем a bв a_b).
Стефан Шазелас
@Stephane: это означает, что нужно выполнить одну и ту же renameкоманду дважды?
Маркус Пшеидт
Ну, больше похоже на столько раз, сколько вложенных уровней каталогов с пробелами. В идеале сначала необходимо пройти глубину каталога и преобразовать только базовое имя файла, как в принятом решении. Также обратите внимание, что bash **исключает точечные файлы и пересекает символические ссылки.
Стефан Шазелас
0

Если вы не любите регулярные выражения (а я нет!), И вы можете запускать приложения, разработанные для kde (либо вы используете рабочий стол kde-k, либо у вас установлены его библиотеки), то krename - отличная графическая утилита, которая позволяет увидеть до и после, прежде чем вы передаете изменения. Он имеет ряд простых преобразований в качестве параметров, а также поддерживает регулярные выражения. Вы даже можете объединить несколько последовательных преобразований в одно переименование, чтобы вам не приходилось проектировать одно сложное преобразование, которое выполняет все сразу. Он также имеет возможность продолжить переименование тех же файлов после применения переименования.

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

http://www.krename.net/

Джо
источник