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

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

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,

2 ответа

Решение

Не анализируйте имена файлов с 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

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

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

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

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

Другие вопросы по тегам