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

Я пытаюсь переименовать такие файлы:

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

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

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

EDIT: Например: файл trip: hill, следует переименовать: trip_ hill, но команда выше делает его trip__hill.

10
задан 22 December 2017 в 19:03

6 ответов

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

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

sudo apt install rename

Затем:

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

Примечания

удалите -n после тестирования, чтобы фактически переименовать файлы [ f10] в случае, если какой-либо файл начинается с символов - [^-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
ответ дан 22 May 2018 в 15:59
  • 1
    Эта команда работает благодаря вам. Вы также четко определили ошибки в команде, которую я использовал. – latach 22 December 2017 в 18:33
  • 2
    Еще раз спасибо. Обратите внимание, что нет необходимости использовать косую черту '\' в случае использования sed. Потому что это добавляет '\' в список игнорируемых символов. – latach 22 December 2017 в 18:52
  • 3
    @latach Это обратная косая черта, но вы абсолютно правы. После тестирования и копания я обнаружил, что . является литералом в классе символов. TIL! – Zanna 22 December 2017 в 19:02

Не разбирайте имена файлов с помощью 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

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

12
ответ дан 18 July 2018 в 00:39

Не разбирайте имена файлов с помощью 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

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

12
ответ дан 24 July 2018 в 17:15

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

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

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

2
ответ дан 22 May 2018 в 15:59

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

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

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

2
ответ дан 18 July 2018 в 00:39

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

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

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

2
ответ дан 24 July 2018 в 17:15

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

Похожие вопросы: