як перейменувати кілька файлів, замінивши рядок у назві файлу? цей рядок містить "#"


42

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-certain-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

Ці згадані статті відповіли на моє запитання. Однак жоден з них не працює на мене. Я підозрюю, що це тому, що рядок, який я намагаюся замінити, має в ньому #. Чи існує особливий спосіб вирішити це?

У мене є файл зображення, який під час міграції сайту замінив е # U00a9. Вони виглядають приблизно так:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

і я хочу змінити це на щось подібне:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

ОНОВЛЕННЯ:

Усі ці приклади починаються з "LU00a9ucky, але тут є багато зображень з різними іменами. Я просто націлюю частину рядка" # U00a9 ", щоб замінити на" безпечний ".


3
То що ви насправді пробували? Я бачу, що ви пов’язали кілька запитань і сказали, що вони не змогли, але як вони провалилися? Найкращим прикладом IMO є renameкоманда. Я підозрюю, що ваше перейменування було б таким же простим rename -n 's/#/safeNBC/' *.jpg.
— Зоредаче

Я спробував, rename -n 's/#U00a9/safe/' *.jpgі команда була прийнята, але змін не відбулося.

Звичайно, як ви бачили з документації, яку ви неодмінно переглядали, -nце no actваріант. Що дозволяє вам бачити, чи працює він, перш ніж ви його фактично використовуєте. Чи правильно показано на виході на екрані потенційні нові імена?
— Зоредаче

Прошу вибачення, що скопіював і вставив ваш приклад, не приділяючи всієї уваги, я виконав команду перейменування без -n. Я вважаю, що @DTK вирішив проблему, я не уникав #.

Заміна рядків у іменах файлів на MacOS: superuser.com/questions/152627/…
— Антон Тарасенко,

Відповіді:


64

Для того, щоб замінити #на somethingelseімена файлів в поточному каталозі (НЕ рекурсивний) , ви можете використовувати GNU перейменування утиліти:

rename  's/#/somethingelse/' *

Таких персонажів, як, наприклад, -треба уникати \.

Для вашого випадку ви хочете використовувати

rename 's/#U00a9/safe/g' *

Зауважте, що якщо ви хочете оперувати лише певним вибором файлів, наприклад, лише *.jpg, налаштуйте підсумковий вхід відповідно до цього вибору:

rename 's/#U00a9/safe/g' *.jpg

Щоб виконати тест перед тим, як фактично змінити імена файлів, використовуйте -nпрапор:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

Для OS X перейменування GNU можна встановити за допомогою homebrew : brew install rename.


Це не працювало на моїй машині (Arch Linux), але відповідь mik зробила.
— marcvangend

@marcvangend Яку версію renameви використовуєте? # sudo pacman -S perl-renameвстановить версію perl, яка є більш потужною і може бути достатньою, щоб ця відповідь працювала для вас.
— Джон Гоуерс

@JohnGowers Дякую! Я не розумів, що існує дві версії. У моїй системі rename --versionповертається rename from util-linux 2.29.2так, що насправді не є версією perl.
— marcvangend

5
Є дві загальні renameутиліти, але жодна з них не розробляється GNU: Дистрибутиви на основі Debian містять renameутиліту зі своїм пакетом Perl, тоді як дистрибутиви на основі Red Hat використовують renameутиліту util-linuxвід організації Linux Kernel. Ваше посилання на renameC функції зі стандартної бібліотеки GNU.
— Ентоні Г - справедливість для Моніки

2
У цій відповіді, чому ми повинні писати /gвrename 's/#U00a9/safe/g' *
— Nikhil

21

знайти список файлів та замінити ключове слово. нижче приклад

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;

1
Вам потрібні подвійні цитати навколо ваших mvаргументів, якщо у назві є пробіли
— Зупиніть шкодити Моніці

Мені потрібно було замінити всі файли * _spec.rb на * _controller_spec.rb, і ваше рішення працювало на мене. Дякую.
— jedi

18

Це не важко, просто переконайтесь, що уникнути октоторпа (#) в імені, попередньо передбачивши зворотний проріз (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 

Ваше пояснення має сенс, уникаючи #звуків, як те, що мені потрібно. Я не бачу зворотної косої риси у вашому прикладі. Чи має це виглядати так: s/\#U00a9/safe/

@LeonFrancisShelhamer хороший улов. Це проковтнуло зворотний кут. Я модифікую.

17

Щоб вийти #з оболонки, просто використовуйте одинарні лапки ( '#'), подвійні лапки ( "#") або зворотну косу рису ( \#).

Найпростішим у вашому випадку буде використання renameкоманди (якщо вона є):

rename '#U00a9' safe *.jpg

2
Спасибі. Хоча відповідь з найвищим голосом ( rename 's/#/somethingelse/' *) не працював на моїй машині (Arch Linux), ця відповідь була.
— marcvangend

1
Це працює за допомогою команди перейменування від util-linux.
— нечистий

10

не впевнений, як в sed, але ви можете спробувати це в bash shell:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

пояснення:

  1. прокручує всі назви файлів, що відповідають глобусу (Lucky- # U00a9NBC - *. jpg)
  2. перейменує файл за допомогою команди переміщення (mv)
  3. використовує заміну базового параметра bash $ {var / Pattern / Replacement} для створення нового імені ("$ {f / # U00a9 / safe}")

Детальніше про підстановку параметрів (яка сильно недооцінюється ІМО): http://www.tldp.org/LDP/abs/html/parameter-substitution.html


Хоча цей код може відповісти на питання, він не дуже корисний сам по собі. Пояснення, як воно вирішує проблему, поліпшило б корисність та довгострокове значення відповіді.
— Ентоні Г - справедливість для Моніки

додано покрокове пояснення та подальше читання відповідно до коментаря Ентоні.
— Грегорі Патмор

1

Наведені вище приклади не працювали в моїй системі (CentOS 5.6), тому я знайшов (можливо, більш специфічну для системи) команду, яка працює (зверніть увагу: потрібно втекти "#" з \командного рядка):

rename \#U00a9 safe *.jpg

[Також: У мене поки що недостатньо репутації для коментарів, тому у відповідь на запитання Нікіля щодо використання /gв rename 's/old_string/new_string/g'(поставлено в коментарях до іншої відповіді вище):

Використовуйте gмодифікатор, щоб здійснити «глобальну» заміну (тобто замінити new_string на old_string стільки разів, скільки відбувається old_string). У моїй відповіді це не повинно бути необхідним, оскільки цей renameфайл буде застосовано до всіх файлів, вказаних у *. Див. Https://www.computerhope.com/unix/rename.htm для стислого пояснення цього та інших модифікаторів.]


Правильно; Операційні системи, отримані від Fedora, як CentOS, мають іншу версію, renameніж ОС, що походять від Debian. Дивіться unix.stackexchange.com/a/238862/135943 . І до речі, CentOS 5.6 досить старий, і рекомендую оновити.
— Wildcard

Ах, дякую за пояснення + посилання. Застаріла ОС працює на роботі, і тому мені не вдається модернізувати :), але створюється новий кластер, і, імовірно, ми будемо модернізувати, коли ми перейдемо далі ...
— Ezra Citron

0

Ось DTK-рішення, укладене у функцію bash для багаторазового використання:

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

Ось як ви можете ним скористатися:

renameFilesRecursively /home/user/my-files apple orange

0

Насправді renameє варіант саме для того, що називається --substабо -sкоротше. Не потрібно використовувати синтаксис регулярних виразів.

rename -s '#U00a9' 'safe' *

Якщо ви хочете замінити / замінити кілька випадків, використовуйте --subst-allабо -S.

До речі, я хотів лише замінити рядок нічим (видалити його з імені файлу) ... ну у нас також є варіант для цього -d/--deleteі -D/--delete-all:

rename -d '#U00a9' *

-1

Ще один варіант - використання pyRenamerпрограми, створеної спеціально для перейменування партії.

Його можна встановити за допомогою sudo apt-get install pyrenamer

Детальну інформацію про використання див. У файлі README на GitHub .


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