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


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

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,


10
2017-12-22 13:39


происхождения


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


ответы:


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

использование rename, В 17.10 вам нужно сначала установить его

sudo apt install rename

Затем:

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

Заметки

  • Удалить -n после тестирования, чтобы фактически переименовать файлы
  • -- end-of-options, если любой файл начинается с -
  • [^-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

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


12
2017-12-22 14:27



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


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

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

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


2
2017-12-25 19:53