Відповіді:
Для кращого рішення (з лише функцією bash, на відміну від зовнішніх дзвінків), дивіться одну з інших відповідей .
Далі робиться та не вимагає, щоб система мала rename
програму (хоча це найчастіше у вас є в системі):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
EDIT: Як зазначалося в коментарях, це не працює для назви файлів з пробілами в них без належного цитування (тепер додано вище). Якщо ви працюєте виключно над власними файлами, за якими ви знаєте, що у файлах файлів немає пробілів, це буде працювати, але коли ви пишете щось, що може бути використане згодом, не пропускайте належне цитування.
ren *.a *.b
$()
замість застарілого синтаксису backtick. Покращує читабельність і робить синтаксис набагато менш неоднозначним, коли у вас є символи, які потребують відхилення від косої риски, щоб бути буквальним усередині підстановки команди останньою.
Якщо ви використовуєте bash, немає необхідності у зовнішніх командах, таких як sed, basename, rename, expr тощо.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
"${file%.*}.txt"
, але це може бути небезпечно для файлів без розширення.
$
всередині фігурних дужок немає!
--
"operator": mv - "$ file" "$ {file% .html} .txt" Цей оператор запобігає імен файлів, які починаються з a "-" від розбору mv як аргументів.
rename 's/\.html$/\.txt/' *.html
робить саме те, що ти хочеш.
Це працювало для мене на OSX від .txt до .txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
.txt
.txt_bak
_bak
.scss
на .sass
(після перетворення на місці…):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Ви хочете використовувати rename
:
rename -S .html .txt *.html
Це робить саме те, що ви хочете - це змінить розширення з .html
на .txt
всі файли, які відповідають *.html
.
Примітка: Грег Х'югілл правильно зазначає, що це не башти, вбудовані; і є окремою командою Linux. Якщо вам просто потрібно щось на Linux, це повинно працювати добре; якщо вам потрібно щось більше крос-платформне, то подивіться на одну з інших відповідей.
rename
програма не пов'язана з нею bash
і також доступна не на всіх платформах. Я бачив це лише в Linux.
rename -S .html .text *.html
там, де -S
стоїть--subst-all
На Mac ...
brew install rename
rename -S .html .txt *.html
Для користувачів Ubuntu:
rename 's/\.html$/\.txt/' *.html
Ось приклад команди перейменування:
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
Це питання прямо згадує Bash, але якщо у вас є ZSH в наявності, це досить просто:
zmv '(*).*' '$1.txt'
Якщо ви отримаєте, zsh: command not found: zmv
то просто запустіть:
autoload -U zmv
А потім спробуйте ще раз.
Завдяки цій оригінальній статті для підказки про zmv.
Після того, як чийсь веб-сайт перескакував, я виявив, що у широкому дереві підкаталогів тисячі файлів пропустили розширення .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"
Потрібно виправити: робота з пробілами у назви файлів
Командаmmv
, здається, дуже ефективно виконати це завдання на величезну кількість файлів (десятки тисяч в секунду). Наприклад, щоб перейменувати всі .xml
файли у .html
файли, використовуйте це:
mmv ";*.xml" "#1#2.html"
;
буде відповідати шляху, то *
буде збігатися з ім'ям файлу, і вони згадуються як #1
і #2
в ім'я заміни.
Відповіді на основі exec
труб були або занадто повільними, або не вдалися до дуже великої кількості файлів.
Трохи запізнюємось на вечірку. Ви можете зробити це за допомогою 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' - {}
ls
. Ця команда смішна: вона марно використовує глобус ls
, а не безпосередньо використовує глобус. Це порушиться з назви файлів, що містять пробіли, лапки та (через відсутність лапок) глобальних символів.
Це хороший спосіб змінити кілька розширень одночасно:
for fname in *.{mp4,avi}
do
mv -v "$fname" "${fname%.???}.mkv"
done
Примітка: будьте обережні, щоб розмір розширення був однаковим (???)
Якщо ви віддаєте перевагу PERL, існує короткий сценарій PERL (спочатку написаний Ларрі Уолл, творець PERL), який зробить саме те, що ви хочете тут: tips.webdesign10.com/files/rename.pl.txt .
Для вашого прикладу слід зробити фокус:
rename.pl 's/html/txt/' *.html
Один рядок, без циклів:
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
На жаль, це не банально робити портативно. Напевно, вам потрібно трохи чарівництва expr.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Видаліть відлуння, коли ви щасливі, він робить те, що вам хочеться.
Правка: basename
напевно, трохи читабельніше для цього конкретного випадку, хоча expr
загалом є більш гнучким.
Ось що я використовував для перейменування .edge
файлів.blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Працює як шарм.
Ви також можете зробити функцію в 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
Перейменуйте розширення файлів для всіх файлів у поточному каталозі та підкаталогах без будь-яких інших пакетів (використовуйте лише скрипт оболонки):
Створіть скрипт оболонки rename.sh
під поточним каталогом із наступним кодом:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
done
Виконати його ./rename.sh .old .new
.
Напр. ./rename.sh .html .txt