Избегайте замены пробелов при переименовании файлов

10

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

for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done

Но sedкоманда заменяет все пробелы на _.

Как я могу отредактировать sedкоманду, чтобы она содержала пробелы вместе с указанными символами? Я пытался использовать, \sно это не работает ...

РЕДАКТИРОВАТЬ:
Например: файл trip: hill, должен быть переименован:, trip_ hillно команда выше делает это trip__hill.

Занна
источник
Я перемещаю некоторые файлы из Linux в Mac. Но по какой-то причине система Mac не может прочитать все имена файлов, поэтому я пытаюсь переименовать мои файлы. Добавление пробела к команде выше не работает. И вы правы: я хочу заменить все символы на '_', кроме указанных. И я не знаю, как включить космический символ.
Обратите внимание, что я пытаюсь заменить все символы на «_», кроме указанных. Для переименованных файлов нет определенного шаблона, поэтому я не могу использовать эту команду perl.

Ответы:

11

Не анализируйте имена файлов с помощью sed! Вывод echo "$file"может быть не надежным.

Использование rename. 17.10 сначала нужно установить

sudo apt install rename

Потом:

rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *

Заметки

  • удалить -nпосле тестирования, чтобы фактически переименовать файлы
  • -- конец опций, если любой файл начинается с -
  • [^-A-Za-z0-9_ .]символы, которые мы не хотим заменять - ставьте -первым или последним, чтобы он не мог указывать диапазон (он обрабатывается буквально в этих позициях).
  • Пробелы могут быть включены в класс
  • . трактуется буквально (в других контекстах регулярных выражений он обозначает любой символ и должен быть экранирован).

Это также работает в sed:

$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill

Если я добавлю пробел в конец вашей версии, я получу сообщение об ошибке:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end

Но -в конце это работает:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill

Так что, возможно, положение дефиса вызвало вашу проблему, когда вы добавили пробел. Но совет не разбирать имена файлов стоит!

Занна
источник
Эта команда работает спасибо. Вы также четко определили ошибки в команде, которую я использовал.
2
Еще раз спасибо. Обратите внимание, что нет необходимости использовать косую черту '\' в случае использования sed. Потому что это добавляет «\» в список игнорируемых символов.
2
@latach Это обратный слеш, но ты абсолютно прав. После тестирования и копания я обнаружил, что .это буквально в классе персонажей. TIL!
Занна
2

Вы также можете просто использовать оболочку, расширение параметра Bash может сделать замену:

for f in ./* ; do
    mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done

Двойная косая черта говорит ему заменить все совпадения, кроме этого, синтаксис прост.

ilkkachu
источник