Як перейменувати розширення для групи файлів?


479

У каталозі я маю купу *.htmlфайлів. Я хотів би перейменувати їх на всі*.txt

Як я можу це зробити? Я використовую оболонку bash.

Відповіді:


382

Для кращого рішення (з лише функцією bash, на відміну від зовнішніх дзвінків), дивіться одну з інших відповідей .


Далі робиться та не вимагає, щоб система мала renameпрограму (хоча це найчастіше у вас є в системі):

for file in *.html; do
    mv "$file" "$(basename "$file" .html).txt"
done

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


47
Альтернатива, без базового імені та з лапками: mv "$ {file}" "$ {file /%. Html / .txt}" (детальніше див. Man bash, Розширення параметрів)
Rodrigo Queiro

7
Добре, лише якщо файли знаходяться в поточному каталозі, звичайно, тому що базове ім’я знімає частину імені шляху. Просто "остерігайся"!
Джонатан Леффлер

6
Це рішення є поганим не лише тому, що воно повільне, але й тому, що воно не працює з назви файлів і з пробілами в них. ВИНАГИ слід правильно робити цитати в скриптах bash. mv "$ file" "$ (базове ім'я" $ file ".html)". txt було б набагато краще. Але все ж mv "$ files" "$ {files% .html} .txt" набагато краще.
Balázs Pozsár

8
у вікнах, які ви просто робитеren *.a *.b
Мухаммед Умер

2
Як мінімум, використовуйте вказаний POSIX $()замість застарілого синтаксису backtick. Покращує читабельність і робить синтаксис набагато менш неоднозначним, коли у вас є символи, які потребують відхилення від косої риски, щоб бути буквальним усередині підстановки команди останньою.
Чарльз Даффі

668

Якщо ви використовуєте bash, немає необхідності у зовнішніх командах, таких як sed, basename, rename, expr тощо.

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done

12
І якщо ви не знаєте розширення файлу, яке ви можете використовувати "${file%.*}.txt", але це може бути небезпечно для файлів без розширення.
Джесс

1
Зауважте, хто має проблеми з цим, як це було у мене: зауважте, що $всередині фігурних дужок немає!
doug65536

5
Мені потрібен спосіб назавжди
вподобати / заповнити

7
@danip Конструкція відсотка-знак у межах дужки знімає символи з кінця. Також є конструкція хеш-дужки, яка знімає символи з початку. Перевірте це: tldp.org/LDP/abs/html/parameter-substitution.html#PSUB2

4
Інша відповідь обміну стеками (що я не можу знайти!) Запропонувала це, але також використовуючи --"operator": mv - "$ file" "$ {file% .html} .txt" Цей оператор запобігає імен файлів, які починаються з a "-" від розбору mv як аргументів.
rcreswick

191
rename 's/\.html$/\.txt/' *.html

робить саме те, що ти хочеш.


Я не думаю, що ти можеш використовувати буквальний регулярний вираз у bash, як ти пропонуєш - яку оболонку ти використовуєш?
DaveR

1
Я використовую термінал Mac
bmw0128

Ось сторінка людей для версії перейменування на Ubuntu: unixhelp.ed.ac.uk/CGI/man-cgi?rename
Amber

Перейменувати - це команда в деяких системах. У мене є сценарій Perl (спочатку з першої книги Camel), який робить цю роботу. Також є однойменна програма GNU, яка виконує приблизно таку ж роботу. У моєму Mac немає системної команди "перейменувати", або вона не входить в мій PATH (який є досить вичерпним).
Джонатан Леффлер

Існує формула перейменування в домашній.
revprez

112

Це працювало для мене на OSX від .txt до .txt_bak

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;

4
Добре працює і в Linux.
Дізіет

Це окрім .txt.txt_bak_bak
суті

3
Це приємно для перейменування рекурсивно
leachryanb

Чудово! (під Ubuntu 16.04) Мій випадок практичного використання, перейменувавши всіх .scssна .sass(після перетворення на місці…):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Frank Nocke

2
це працювало з +6000 файлами, перейменував повідомлення про "аргумент списку занадто довгий"
Тоні Кронін

94

Ви хочете використовувати rename:

rename -S .html .txt *.html

Це робить саме те, що ви хочете - це змінить розширення з .htmlна .txtвсі файли, які відповідають *.html.

Примітка: Грег Х'югілл правильно зазначає, що це не башти, вбудовані; і є окремою командою Linux. Якщо вам просто потрібно щось на Linux, це повинно працювати добре; якщо вам потрібно щось більше крос-платформне, то подивіться на одну з інших відповідей.


7
Хоча це гарне рішення, renameпрограма не пов'язана з нею bashі також доступна не на всіх платформах. Я бачив це лише в Linux.
Грег Хьюгілл

15
"$ rename .html .txt * .html" призводить до ... синтаксичної помилки в (eval 1) рядку 1, поблизу ".
Бурштин

8
Правильний синтаксис стоїть rename -S .html .text *.htmlтам, де -Sстоїть--subst-all
Марек Себера

8
brew install prename
Нік

4
@GregHewgill перейменування доступне для Mac OS з HomeBrew
CodeBrauer



9

Це найрізкіше рішення, яке я знайшов, що працює на OSX та Linux, і воно чудово працює і з git!

find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;

і з git:

find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;


8

Ось приклад команди перейменування:

rename -n s/\.htm$/\.html/’ *.htm

-N означає, що це тестовий запуск і фактично не змінить жодних файлів. Він покаже вам список файлів, які будуть перейменовані, якщо ви видалили -n. У наведеному вище випадку він перетворить усі файли в поточному каталозі з розширення файлу .htm в .html.

Якщо вихід з вищевказаного тестового запуску виглядав нормально, тоді можна запустити остаточну версію:

rename -v s/\.htm$/\.html/’ *.htm

-V необов’язковий, але добре його включити, тому що це єдиний запис, який ви будете мати зміни, які були внесені командою перейменування, як показано у наведеному нижче прикладі:

$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html

Хитра частина в середині - це заміна Perl з регулярними виразами, виділеними нижче:

rename -v s/\.htm$/\.html/’ *.htm

6

Це питання прямо згадує Bash, але якщо у вас є ZSH в наявності, це досить просто:

zmv '(*).*' '$1.txt'

Якщо ви отримаєте, zsh: command not found: zmvто просто запустіть:

autoload -U zmv

А потім спробуйте ще раз.

Завдяки цій оригінальній статті для підказки про zmv.


4

Після того, як чийсь веб-сайт перескакував, я виявив, що у широкому дереві підкаталогів тисячі файлів пропустили розширення .html.

Щоб перейменувати їх за один кадр, за винятком файлів, які вже мають розширення .html (у більшості з них не було жодного), це працювало для мене:

cd wwwroot
find . -xtype f \! -iname *.html   -exec mv -iv "{}"  "{}.html"  \;  # batch rename files to append .html suffix IF MISSING

У випадку ОП я можу це трохи змінити, щоб перейменовувати * .txt файли, як-от так:

find . -xtype f  -iname *.txt   -exec filename="{}"  mv -iv ${filename%.*}.{txt,html}  \; 

Зламаний (молот!):

-iname * .txt
- означає розглянути файли, які вже закінчуються у .txt

mv -iv "{}. {txt, html}" - Коли знахідка передає {} як ім'я файлу, $ {filename%. *} витягує його базове ім'я без будь-якого розширення, щоб сформувати параметри mv . bash приймає {txt, html}, щоб переписати його як два параметри, тож остаточна команда працює як:mv -iv "filename.txt" "filename.html"

Потрібно виправити: робота з пробілами у назви файлів


4

Командаmmv , здається, дуже ефективно виконати це завдання на величезну кількість файлів (десятки тисяч в секунду). Наприклад, щоб перейменувати всі .xmlфайли у .htmlфайли, використовуйте це:

mmv ";*.xml" "#1#2.html"

;буде відповідати шляху, то *буде збігатися з ім'ям файлу, і вони згадуються як #1і #2в ім'я заміни.

Відповіді на основі execтруб були або занадто повільними, або не вдалися до дуже великої кількості файлів.



3

Трохи запізнюємось на вечірку. Ви можете зробити це за допомогою xargs:

ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}

Або якщо всі ваші файли знаходяться в якійсь папці

ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}

3
Ні. Не розбирайтеls . Ця команда смішна: вона марно використовує глобус ls, а не безпосередньо використовує глобус. Це порушиться з назви файлів, що містять пробіли, лапки та (через відсутність лапок) глобальних символів.
gniourf_gniourf

FYI, Ваша пов’язана стаття містить оновлену примітку, в якій сказано, що нові LS "правильно" втеча від оболонки ", якщо надруковані на терміналі". Ваша думка все ще є хорошим правилом.
Катастичне подорож

3

Це хороший спосіб змінити кілька розширень одночасно:

for fname in *.{mp4,avi}
do
   mv -v "$fname" "${fname%.???}.mkv"
done

Примітка: будьте обережні, щоб розмір розширення був однаковим (???)



2

Якщо ви віддаєте перевагу PERL, існує короткий сценарій PERL (спочатку написаний Ларрі Уолл, творець PERL), який зробить саме те, що ви хочете тут: tips.webdesign10.com/files/rename.pl.txt .

Для вашого прикладу слід зробити фокус:

rename.pl 's/html/txt/' *.html

2
На це питання вже давно відповіли та прийняли, і не здається, що ваша відповідь приносить щось більше, ніж вже сказане.
ChristopheLec

1
+1, оскільки це був сценарій Ларрі Уолл (модифікований Робіном Баркером). Остання доступна URL-адреса така: tips.webdesign10.com/files/rename.pl.txt
loretoparisi

1

Аналогічно тому, що було запропоновано раніше, ось так я це зробив:

find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;

Я вперше підтвердив с

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;

1

Один рядок, без циклів:

ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}

Приклад:

$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json  ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt  ac8453e2-0d82-4d43-b80e-205edb754700.txt

+1 для показу лише баш-способу, який не залежить від точно узгодження існуючого розширення. Це працює для будь-якого розширення на вхід, будь то 3 символи або 4 символи довше або більше
Ciprian Tomoiagă

0

На жаль, це не банально робити портативно. Напевно, вам потрібно трохи чарівництва expr.

for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done

Видаліть відлуння, коли ви щасливі, він робить те, що вам хочеться.

Правка: basename напевно, трохи читабельніше для цього конкретного випадку, хоча exprзагалом є більш гнучким.


Хоча це не найкраща відповідь на питання, це було для мене! Мені потрібен був спосіб перейменувати лише в рядку цілий шлях, а не лише ім'я файлу. Дякуємо за публікацію!
пончик

0

Ось що я використовував для перейменування .edgeфайлів.blade.php

for file in *.edge; do     mv "$file" "$(basename "$file" .edge).blade.php"; done

Працює як шарм.


0

Ви також можете зробити функцію в Bash, додати її до .bashrcчогось іншого, а потім використовувати її де завгодно.

change-ext() {
    for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}

Використання:

change-ext css scss

Джерело коду у функції: https://stackoverflow.com/a/1224786/6732111


0

Перейменуйте розширення файлів для всіх файлів у поточному каталозі та підкаталогах без будь-яких інших пакетів (використовуйте лише скрипт оболонки):

  1. Створіть скрипт оболонки rename.shпід поточним каталогом із наступним кодом:

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
  2. Виконати його ./rename.sh .old .new.

    Напр. ./rename.sh .html .txt

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