Як змінити розширення кількох файлів?


166

Я хотів би змінити розширення файлу з *.txtна *.text. Я спробував скористатися basenameкомандою, але у мене виникли проблеми зі зміною декількох файлів.

Ось мій код:

files=`ls -1 *.txt`

for x in $files
do
    mv $x "`basename $files .txt`.text"
done

Я отримую цю помилку:

basename: too many arguments Try basename --help' for more information

Відповіді:


175

Прямо з Вікі Грега :

# Перейменуйте всі * .txt в * .text
для f в * .txt; робити
    mv - "$ f" "$ {f% .txt} .text"
зроблено

Також дивіться запис про те, чому вам не слід розбиратиls .

Редагувати: якщо вам доведеться використовувати basenameваш синтаксис, було б:

для f в * .txt; робити
    mv - "$ f" "$ (базове ім'я -" $ f ".txt) .text"
зроблено

48
Тут використовується трохи вдосконалений синтаксис Баша без пояснень. Мені довелося багато речей зрозуміти Google. Щоб допомогти іншим в моєму положенні, ось декілька посилань на глобуси ( *.txtсинтаксис) , голий подвійний тире-- та використання символу% у ${}конструкції . До цих пір я ніколи не стикався з останніми двома і не знав, що насправді відбувається з першим.
— Марк Амері

3
Подивіться на відповідь Маттіаса Брауна нижче - набагато простіше, те ж саме.
— btk

10
Один лайнерfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
— Марсал Хуан

1
Ви пропали безвісти; після тексту ".
— Петур Інгі Егілссон

2
@ PéturIngiEgilsson на другому рядку? Ні, це не потрібно.
— jasonwryan

132

Ось як я змінюю всі розширення файлів у поточному каталозі на Debian.

rename "s/oldExtension/newExtension/" *.txt

(Це renameкоманда Perl , а не util-linuxодна. Дивіться, чому утиліта перейменування на Debian / Ubuntu відрізняється від тієї в інших дистрибутивах, як CentOS? )


10
Набагато простіше, ніж прийнята відповідь, дякую!
— btk

8
На Mac я зміг brew install renameце зробити.
— Monkpit

3
з рибною шкаралупою можна зробити rename "s/oldExtension/newExtension/" **.txtперейменування всіх * .txt рекурсивно
— Palmstrom

3
Це не вдасться footxt.txt. Використовуйте це замість: unix.stackexchange.com/questions/19654/…
— wisbucky

7
Коли ваші файли не мають жодного розширення, і ви хочете додати його:rename 's/$/.txt/' *
— mkataja

34

Проста команда, renameвідutil-linux , зробить це для вас, вона замінить усі випадки "txt" на "текст" у всіх файлах, що відповідають "* .txt":

rename txt text *.txt

4
renameзмінює перше виникнення, тому краще зробіть це rename .txt .text, але це все одно не завжди працюватиме (наприклад, воно перейменовується foo.txtx.bar.txtна foo.textx.bar.txt).
— Жиль

12
Слід зазначити, що не всі системи мають однакову версію перейменування; на Debian та друзях renameкоманда є фактично perl-renameта використовує регексети perl. Для цього, еквівалентна команда буде: rename 's/.txt/.text/' *.txt. Люди повинні перевірити, чи є man renameу них система.
— злий

@evilsoup Це стосується OSX, thx
— Даві Ліма

Це також працює на Cygwin (Windows)
— Енді

27
rename "s/oldExtension/newExtension/" *.txt

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

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;

2
renameВи можете обробляти декілька файлів як аргумент, ви можете значно прискорити роботу, використовуючи +замість того, \;якщо таких файлів багато
— Anthon

Але це корисна опція, оскільки "* .txt" може перейти до великого списку аргументів, що не підтримується оболонкою.
— Роман Шаповалов

1
"s / oldExtension / newExtension /" не вдасться footxt.txt. Використовуйте це замість: unix.stackexchange.com/questions/19654/…
— wisbucky


9

Відповіді, на які посилаються тут s/oldExtension/newExtension/, неправильні. Якщо ви використовуєте s/txt/text/, ви б конвертувати footxt.txtв footext.txt, який не те , що ви хочете. Навіть якщо ви використовуєте s/.txt/.text/, це перетвориться footxt.txtна fo.text.txt.

Ви повинні використовувати, \.щоб відповідати періоду ( .відповідатиме будь-якому символу). І трейлінг, $щоб відповідати кінці рядка. Тільки це правильно відповідатиме розширенням.

rename 's/\.txt$/.text/' *.txt

rename 's/\.old$/.new/' *.old

7

На основі відповіді @Prince Джона Веслі, ось простий скрипт для зміни всіх розширень файлів у поточному каталозі з ext1на ext2. Виводить також імена файлів, які перейменовані.

#!/bin/bash
for f in *.$1
do
    [ -f "$f" ] && mv -v "$f" "${f%$1}$2"
done

Приклад використання (якщо вважати ім'я сценарію change-ext):

change-ext ext1 ext2

Щоб змінити розширення файлів у каталогах рекурсивно, замініть другий рядок ( for...) на два рядки: shopt -s globstarі for f in **/*.$1. Потрібен Bash 4+.
— Денніс Голомазов


3

скажімо, ваші файли розкидані в різних каталогах. Припустимо, що dirx - це ваш батьківський каталог, це може зробити роботу, використовуючи пошук:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done

А що з тчш ..
— Йозеф Климук

2

Це те, що працює для мене:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;

1
БУДЬ ЛАСКА додати. перед "текстом"
— danielmhanover

2

Коли ти

не мають розширення для вихідних файлів

а розширення цілі - це .текст, ви зробите це так -

for f in *; do mv -- "$f" "${f%.\*}.text"; done

1
Відмінний баш-рідний сценарій. працював чудово! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
— TamusJRoyce

1

Якщо ви хочете знати, що пішло не так у вашій версії: Ви використовували $filesзамість команди $xbasename. Отже, це має працювати (проте не перевірено):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.