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


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.