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


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.