Заміна крапок у назві файлу підкресленнями, крім розширення


9

Може хтось підкаже, як перейменувати ім’я файлу:

head.body.date.txt

До:

head_body_date.txt

Чи є одна заява рядка для перейменування в Unix ?


9
Ви припускаєте, що .tar.gzце розширення? Також ласкаво просимо до U&L!
EKons

2
Ви дійсно маєте на увазі Unix на відміну від Linux? Який Unix?
terdon

1
Очевидна відповідь mv head.body.date.txt head_body_date.txt. Якщо у вас є інші обмеження чи реальні приклади, то будь ласка, оновіть своє запитання. Наразі незрозуміло, чи стосується цього питання файл із цим явним іменем, єдиний каталог, де всі файли мають певний формат, чи потрібно шукати в ієрархії каталогів конкретні імена та змінювати їх.
Kusalananda

Відповіді:


9

Ітерація над іменами та використання розширення параметрів для перетворення:

for f in *.*.*.txt; do i="${f%.txt}"; echo mv -i -- "$f" "${i//./_}.txt"; done

Шаблон розширення параметра ${f//./_}замінює всі .s на _s у файлі ( $f).

Вищенаведене буде виконувати сухий перебіг, щоб перешкодити фактичному перейменуванню echo:

for f in *.*.*.txt; do i="${f%.txt}"; mv -i -- "$f" "${i//./_}.txt"; done

Якщо ви хочете мати справу з будь-яким розширенням, а не тільки .txt:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     echo mv -i -- "$f" "${pre//./_}.${suf}"; done

Після перевірки видаліть echoдійсні дії:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     mv -i -- "$f" "${pre//./_}.${suf}"; done

Загальна, для довільної кількості крапок, принаймні одна:

for f in *.*; do pre="${f%.*}"; suf="${f##*.}"; \
                 mv -i -- "$f" "${pre//./_}.${suf}"; done

чи є загальний спосіб, якщо є довільна кількість крапок?
Ciprian Tomoiagă

1
@CiprianTomoiaga Do:for f in *.*; do ...; done
heemayl

Я можу запропонувати поставити *.*шаблон прямо в приклад, оскільки тепер код виглядає так, що він працює лише з фіксованою кількістю крапок.
ilkkachu

@ilkkachu Досить справедливо, відредаговано.
heemayl

Дякую тобі велике, це спрацювало на мене. і деякі навчання!
SG

4

з perlосновоюrename

$ rename -n 's/\.[^.]+$(*SKIP)(*F)|\./_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)
  • \.[^.]+$(*SKIP)(*F) пропустіть цей візерунок і шукайте альтернативні відповідники
  • |\./_/gзамінити всіх .на_

Або, використовуючи негативний lookahead

$ rename -n 's/\.(?![^.]+$)/_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)

Як тільки це нормально, виберіть -nваріант


3
rename 's/\.(?=[^.]*\.)/_/g' *.txt

Використовує заміну regex, щоб знайти всі, крім останнього екземпляра, .у імені файлу (не захоплюючий lookahead) та замінити їх _. Узагальнює, *.*якщо хочете.

(ця конкретна версія, renameздається, встановлена ​​через util-linux). Я використовую Ubuntu 12.04(так, сильно застаріла машина).


2

bash:

old=head.body.date.txt oldb=${old%.*} olde=${old##*.} ; \
mv -- "$old" "${oldb//./_}.${olde}"

(1) Ви повинні використовувати mv --для захисту від "старих" імен файлів, які починаються з -. (2) Вам слід ввести $oldлапки ( "$old"), щоб захистити від "старих" імен файлів, які містять пробіли або символи, спеціальні для оболонки (як *і ?). (3) Ваша відповідь не відповідає в дещо патологічному випадку, коли розширення містить підкреслення: head.body.date.t_xtперейменовується на head_body_date_t.xt.
Скотт

@Scott, спасибі Код тепер налаштовано відповідно до всіх трьох згаданих елементів.
agc

1

Використання mv, sedі revв одному рядку:

mv "head.body.date.txt" "$(echo head.body.date.txt | rev | sed 's/\./_/2g' | rev)"

Якщо ви хочете застосувати його до всіх txtфайлів у поточному представнику, використання глобусів здається складним через те, як mvпрацює, але ви можете зробити forцикл в одноланковому:

for file in *.txt; do mv "$file" "$(echo $file | rev | sed 's/\./_/2g' | rev)"; done

Трохи довше, але ви можете зіставити кілька візерунків у своєму циклі!


2
(1) Arrghhh! Не робіть $(ls …); просто робити for file in *.txt. (2) Ви повинні використовувати більше цитати: mv "$file" "$(…)".
Скотт

Дякую, Скотт, належним чином відмічений та відредагований! Я все ще юнак у шкаралупі, будь ласка, будь ласка;)
Валентин Б.

Заднім числом, використовуючи, renameяк декілька інших, запропонували у своїх відповідях, проте звучить простіше, хоча ...
Валентин Б.

-1
 mv head.body.date.txt head_body_date.txt

Це так само просто, як і для одного файлу одночасно. Ви не вказуєте, чи хотіли б ви це робити рекурсивно в каталозі або в цілому каталозі, так що це було б вашим найзручнішим, швидким рішенням.

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