Уникайте заміни пробілів при перейменуванні файлів


10

Я намагаюся перейменувати такі файли:

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.


Я переміщую деякі файли з Linux, Mac. Але чомусь система Mac не може прочитати всі назви файлів, тому я намагаюся перейменувати свої файли. Додавання пробілу до команди вище не працює. І ви праві: я хочу замінити всі символи на "_", крім вказаних. І я не знаю, як включити пробіл до місця.

Зауважте, що я намагаюся замінити всі символи на "_", крім зазначених. Для перейменованих файлів немає конкретного шаблону, тому я не можу використовувати цю команду perl.

Відповіді:


11

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

Тож можливо позиція дефіса викликала вашу проблему, коли ви додали пробіл. Але порада не розбирати імена файлів стоїть!


Ця команда працює спасибі. Ви також чітко визначили помилки в команді, яку я використав.

2
Ще раз дякую вам. Зауважте, що у випадку використання sed не потрібно використовувати нахил наперед "\". Тому що це додає "\" до списку ігнорованих символів.

2
@latach Це зворотний кут, але ти абсолютно прав. Після тестування та копання навколо я виявив, що .це буквально в класі символів. TIL!
Занна

2

Ви також можете просто використовувати оболонку, розширення параметрів Баша може зробити підміну:

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

Подвійний косий ривок підказує йому замінити всі збіги, крім цього, синтаксис є прямим.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.