Как переименовать расширение для группы файлов?

В каталоге у меня есть куча *.html файлов. Я хочу переименовать их все в *.txt

Как я могу это сделать? Я использую оболочку bash.


person bmw0128    schedule 03.08.2009    source источник


Ответы (27)


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


Следующее будет делать и не требует наличия в системе программы rename (хотя чаще всего она есть в системе):

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

РЕДАКТИРОВАТЬ: Как указано в комментариях, это не работает для имен файлов с пробелами в них без надлежащего цитирования (теперь добавлено выше). При работе исключительно с вашими собственными файлами, которые, как вы знаете, не имеют пробелов в именах файлов, это сработает, но всякий раз, когда вы пишете что-то, что может быть повторно использовано позже, не пропускайте правильное цитирование.

person Mikael Auno    schedule 03.08.2009
comment
Альтернативный вариант без базового имени и с кавычками: mv $ {file} $ {file /%. Html / .txt} (подробности см. В man bash, Расширение параметров) - person Rodrigo Queiro; 04.08.2009
comment
Разумеется, хорошо только в том случае, если все файлы находятся в текущем каталоге, потому что в базовом имени часть пути отсутствует. Просто будьте осторожны! - person Jonathan Leffler; 04.08.2009
comment
если файлов html много, используйте внутренние строковые функции bash вместо basename. - person ghostdog74; 04.08.2009
comment
+1 за использование базового имени; хотя в вопросе указано, что это для оболочки bash, переносимость хорошая! - person akent; 04.08.2009
comment
Это решение плохое не только потому, что оно медленное, но и потому, что оно не работает с именами файлов с пробелами. Вы должны ВСЕГДА делать правильные цитаты в сценариях bash. mv $ file $ (basename $ file .html) .txt было бы намного лучше. Но все же mv $ files $ {files% .html} .txt намного лучше. - person Balázs Pozsár; 04.08.2009
comment
Я согласен с Позсаром. Если вы не будете осторожны, это действительно может стать плохим днем. Просто предупреждение. - person Jim; 04.08.2009
comment
в окнах вы просто делаете ren *.a *.b - person Muhammad Umer; 27.01.2015
comment
все мои файлы (в которых есть пробел) исчезли, за исключением последнего файла, который остался как ‹empt_name› .txt :( - person Anand Rockzz; 12.06.2016
comment
Как минимум, используйте указанный в POSIX $() вместо устаревшего синтаксиса обратной кавычки. Повышает удобочитаемость и делает синтаксис менее двусмысленным, когда у вас есть символы, которые нужно экранировать с помощью обратной косой черты, чтобы они были буквальными внутри подстановки команды последним. - person Charles Duffy; 10.09.2017
comment
@MuhammadUmer Спасибо! Работал! (Просто когда подумал, что вы не можете выполнять пакетные команды в Windows ...) - person Zeta.Investigator; 05.08.2018

При использовании bash нет необходимости во внешних командах, таких как sed, basename, rename, expr и т. Д.

for file in *.html
do
  mv "$file" "${file%.html}.txt"
done
person ghostdog74    schedule 04.08.2009
comment
И если вы не знаете расширение файла, вы можете использовать "${file%.*}.txt", но это может быть опасно для файлов без расширения вообще. - person Jess; 17.12.2013
comment
Обратите внимание на тех, у кого возникли проблемы с тем, чтобы это работало, как у меня: обратите внимание, что внутри фигурных скобок нет $! - person doug65536; 09.02.2014
comment
Мне нужен способ навсегда добавить в избранное / добавить в закладки этот ответ, я никогда не помню точный синтаксис, и в конечном итоге я ищу его в Google - person boliva; 12.02.2014
comment
Есть ли способ сделать эту работу рекурсивной, т.е. даже если файлы для переименования не находятся непосредственно в текущем рабочем каталоге, а в его различных прямых и косвенных дочерних каталогах? - person antred; 23.05.2014
comment
Я не уверен, как это работает? Вы можете объяснить логику команды mv? - person johnlemon; 20.06.2014
comment
Если вы google linux переименуете несколько расширений, вы не найдете этого ответа, вы найдете несколько неудовлетворительных ответов на unix.stackexchange и в конечном итоге потратите некоторое время на выяснение правильного, потому что вы знаете, как работает mv file{1,2}, что приводит к этот ответ. Переименование пакета Linux в Google привело бы меня прямо сюда ... - person Maxime R.; 20.11.2014
comment
@danip Конструкция "знак процента в скобках" удаляет символы с конца. Также существует конструкция хеш-скобок, которая удаляет символы с начала. Проверьте это: tldp.org/LDP/abs/html/parameter-substitution .html # PSUB2 - person ; 11.01.2015
comment
Другой ответ на обмен стеками (который я не могу найти!) Предложил это, но также с использованием оператора --: mv - $ file $ {file% .html} .txt Этот оператор предотвращает имена файлов, начинающиеся с '-', из анализируется mv как аргументы. - person rcreswick; 09.07.2015

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

делает именно то, что вы хотите.

person Amber    schedule 03.08.2009
comment
Я не думаю, что вы можете использовать буквальное регулярное выражение в bash, как вы предлагаете - какую оболочку вы используете? - person DaveR; 04.08.2009
comment
Вот страница руководства для версии переименования в Ubuntu: unixhelp.ed.ac. uk / CGI / man-cgi? переименовать - person Amber; 04.08.2009
comment
переименовать - это команда в некоторых системах. У меня есть сценарий Perl (изначально из первой книги Camel), который выполняет эту работу. Существует также программа GNU с таким же названием, которая выполняет примерно ту же работу. Мой Mac не имеет предоставленной системой команды «переименовать» - или ее нет в моем PATH (который является умеренно всеобъемлющим). - person Jonathan Leffler; 04.08.2009
comment
В Homebrew есть формула переименования. - person revprez; 29.04.2016
comment
Мне нравится твой ответ. Но на самом деле я просто буду использовать rename 's/jpg/png/' *.jpg, это легче запомнить и набрать. Это может вызвать ошибку, если имя файла содержит jpg, поэтому я проверю его перед вводом. - person ramwin; 09.05.2018

Это сработало для меня на OSX от .txt до .txt_bak

find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
person Steven Lizarazo    schedule 04.12.2014
comment
Прекрасно работает и в Linux. - person Diziet; 31.03.2015
comment
Это помимо сути, но для перехода от .txt к .txt_bak вам просто нужно объединить _bak;) - person corwin.amber; 06.07.2016
comment
Это удобно для рекурсивного переименования - person leachryanb; 02.12.2016
comment
Большой! (в Ubuntu 16.04) Мой практический пример использования, переименование всех .scss в .sass (после преобразования на месте…): find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \; - person Frank Nocke; 04.07.2018
comment
это работало с +6000 файлов, список аргументов переименования был слишком длинным - person Tony Cronin; 01.12.2018
comment
Я использовал его в окнах в хуках GIT (что означает оболочку (Linux)) - он отлично работает. Я хотел удалить расширение .tmp, чтобы использовать его немного модифицированным: find. -name '* .txt' -exec sh -c 'mv $ 0 $ {0% .tmp}' {} \; (в случае, если кто-то хочет переименовать расширение ни с чем (удалите расширение файлов .tmp) Thnx @Steven - person Teo; 08.01.2020

Вы хотите использовать rename:

rename -S <old_extension> <new_extension> <files>

rename -S .html .txt *.html

Это сделает именно то, что вы хотите - оно изменит расширение с .html на .txt для всех файлов, соответствующих *.html.

Примечание: Грег Хьюгилл правильно указывает, что это не встроенная функция bash; и представляет собой отдельную команду Linux. Если вам просто нужно что-то в Linux, это должно работать нормально; если вам нужно что-то более кроссплатформенное, взгляните на один из других ответов.

person DaveR    schedule 03.08.2009
comment
Хотя это хорошее решение, программа rename не связана с bash и также доступна не на всех платформах. Я видел это только в Linux. - person Greg Hewgill; 04.08.2009
comment
$ rename .html .txt * .html приводит к ... синтаксической ошибке в строке 1 (eval 1) рядом. - person Amber; 04.08.2009
comment
@Greg: Ах да, ты прав - я всегда думал, что это встроенный bash. Однако я не думаю, что когда-либо встречал систему Linux, в которой ее не было бы; так что, если вам это нужно только для Linux, переименование, вероятно, самый простой метод. - person DaveR; 04.08.2009
comment
Правильный синтаксис: rename -S .html .text *.html, где -S означает --subst-all. - person Marek Sebera; 13.11.2013
comment
Переименование @GregHewgill доступно для Mac OS с HomeBrew - person CodeBrauer; 07.12.2014
comment
Я обновил ответ, чтобы добавить отсутствующий переключатель -S в соответствии с исправлением @MarekSebera. - person Mark Edington; 10.10.2015
comment
Нет опции -S для переименования 2.28.2 util-linux. Хотя он работает и без него. - person Torsten; 22.09.2017
comment
Моя Ubuntu 16 не включает -S для переименования. - person Katastic Voyage; 27.03.2018
comment
Неизвестный вариант: S на ubuntu - person ramwin; 09.05.2018

На Mac ...

  1. Установите переименовать, если вы этого не сделали: brew install rename
  2. rename -S .html .txt *.html
person izilotti    schedule 22.07.2015

Для пользователей Ubuntu:

rename 's/\.html$/\.txt/' *.html
person Bheru Lal Lohar    schedule 27.02.2015
comment
Это не рекурсивно, но у меня сработало на Ubuntu 14.04. - person Max Wallace; 16.04.2016

Это самое привлекательное решение, которое я нашел, которое работает на 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' - '{}' \;

person bdombro    schedule 21.09.2018
comment
Не совсем гладко, так как запускает новый bash для каждого файла. На самом деле, довольно медленно. Используйте pipe и xargs, пожалуйста. - person Holger Jakobs; 10.11.2020
comment
Полагаю, это правда. Я не могу представить себе много случаев, когда вы называете так много файлов, что производительность будет иметь значение. Этот метод может переименовать сотни за секунды. Так что да, я думаю, может быть, это не лучшая производительность, но это отличное решение, если вы этого не сделаете ... - person bdombro; 03.12.2020

В этом вопросе явно упоминается Bash, но если у вас есть ZSH, это довольно просто:

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

Если вы получили zsh: command not found: zmv, просто запустите:

autoload -U zmv

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

Благодаря этой оригинальной статье за совет о zmv.

person Michael Leonard    schedule 20.06.2017
comment
zmv '(*).html' '$1.txt', чтобы использовать определенные расширения файлов из исходного вопроса. - person Alf Eaton; 11.08.2020

Вот пример команды переименования:

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
person A.A    schedule 28.09.2014

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

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

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

Ответы на основе exec или каналов были либо слишком медленными, либо неуспешными для очень большого количества файлов.

person Roko Mijic    schedule 03.11.2017

Одна строчка, без петель:

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
person Christian Bongiorno    schedule 13.05.2019
comment
+1 за отображение способа только для bash, который не зависит от точного соответствия существующему расширению. Это работает для любого расширения ввода, будь то 3 символа или 4 символа или более. - person Ciprian Tomoiagă; 14.02.2020
comment
Улучшение: $ ls -1 | xargs -L 1 -I {} bash -c 'mv $ 1 $ {1%. *}. swift' _ {} - person Denis Kutlubaev; 07.03.2021

Попробуй это

rename .html .txt *.html 

использование:

rename [find] [replace_with] [criteria]
person P Sreedhar    schedule 06.02.2014

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

Чтобы переименовать их все одним выстрелом, за исключением файлов, уже имеющих расширение .html (у большинства из них его вообще не было), это сработало для меня:

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

В случае OP я мог бы немного изменить это, чтобы переименовывать только файлы * .txt, например:

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

Сломано (время молотка!):

-iname * .txt
- означает рассматривать ТОЛЬКО файлы, которые уже оканчиваются на .txt

mv -iv "{}. {txt, html}" - когда find передает {} в качестве имени файла, $ {filename%. *} извлекает его базовое имя без какого-либо расширения для формирования параметров в < сильный> мв. bash принимает {txt, html}, чтобы переписать его как два параметра, поэтому последняя команда выполняется как: mv -iv "filename.txt" "filename.html"

Однако необходимо исправить: работа с пробелами в именах файлов

person Marcos    schedule 03.07.2014

Это хороший способ изменить сразу несколько расширений:

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

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

person Nick De Greek    schedule 22.09.2018

Немного поздно на вечеринку. Вы можете сделать это с помощью 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' - {}
person esp    schedule 17.06.2015
comment
Нет. Не анализируйте ls. Эта команда нелепа: она бесполезно использует глобус с ls вместо прямого использования глобуса. Это нарушит имена файлов, содержащие пробелы, кавычки и (из-за отсутствия кавычек) глобальные символы. - person gniourf_gniourf; 27.06.2016
comment
К вашему сведению, ваша связанная статья содержит обновленное примечание, в котором говорится, что новый LS «правильно экранирует файлы при печати на терминале». Тем не менее, ваша точка зрения остается хорошим практическим правилом. - person Katastic Voyage; 27.03.2018

Красиво и просто!

find . -iname *.html  -exec mv {} "$(basename {} .html).text"  \;
person Deano    schedule 30.04.2019

Подобно тому, что предлагалось ранее, я сделал это следующим образом:

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

Я сначала проверил с помощью

find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
person Carl Bosch    schedule 06.12.2019
comment
мой любимый ответ - person Logemann; 30.11.2020

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

Для вашего примера следующее должно помочь:

rename.pl 's/html/txt/' *.html
person dudusan    schedule 28.06.2013
comment
На этот вопрос уже давно дан ответ и принят, и не похоже, что ваш ответ приносит что-то большее, чем уже было сказано. - person ChristopheLec; 28.06.2013
comment
+1, поскольку это был сценарий Ларри Уолла (измененный Робином Баркером). Последний доступный URL-адрес: tips.webdesign10.com/files/rename.pl.txt - person loretoparisi; 16.06.2016

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

  1. Создайте сценарий оболочки rename.sh в текущем каталоге со следующим кодом:

    #!/bin/bash
    
    for file in $(find . -name "*$1"); do
      mv "$file" "${file%$1}$2"
    done
    
  2. Запустите ./rename.sh .old .new.

    Eg. ./rename.sh .html .txt

person Neo Liu    schedule 03.12.2019

Вот что я использовал для переименования .edge файлов в .blade.php

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

Работает как шарм.

person Nixon Kosgei    schedule 07.02.2018

К сожалению, сделать это не так просто. Вероятно, вам понадобится немного магии expr.

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

Удалите эхо, как только вы будете довольны, что оно делает то, что вы хотите.

Изменить: basename, вероятно, более удобочитаем для этого конкретного случая, хотя expr в целом более гибкий.

person CB Bailey    schedule 03.08.2009
comment
Возможно, это не лучший ответ на вопрос, но он был для меня! Мне нужен был способ переименовать только в строке весь путь, а не только имя файла. Спасибо за публикацию! - person donut; 10.04.2019

Вы также можете создать функцию в 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

person J Kluseczka    schedule 15.08.2019
comment
Если вы получаете сообщение об ошибке «Плохая подстановка», то, вероятно, команда «sh» не указывает на bash. Замените sh на / bin / bash, и он должен работать. - person Wesley De Keirsmaeker; 20.10.2020

Вот решение, использующее AWK. Убедитесь, что файлы находятся в рабочем каталоге. В противном случае, cd в каталог, где расположены файлы html, а затем выполните следующую команду:

for i in $(ls | grep .html); do j=$(echo $i | grep -oh "^\w*." | awk '{print $1"txt"}'); mv $i $j; done
person Rohith    schedule 28.07.2020

Я написал этот код в своем .bashrc

alias find-ext='read -p "Path (dot for current): " p_path; read -p "Ext (unpunctured): " p_ext1; find $p_path -type f -name "*."$p_ext1'
alias rename-ext='read -p "Path (dot for current): " p_path; read -p "Ext (unpunctured): " p_ext1; read -p "Change by ext. (unpunctured): " p_ext2; echo -en "\nFound files:\n"; find $p_path -type f -name "*.$p_ext1"; find $p_path -type f -name "*.$p_ext1" -exec sh -c '\''mv "$1" "${1%.'\''$p_ext1'\''}.'\''$p_ext2'\''" '\'' _ {} \;; echo -en "\nChanged Files:\n"; find $p_path -type f -name "*.$p_ext2";'

В папке типа / home / ‹user› / example-files, имеющей такую ​​структуру:

  • /home/<user>/example-files:
    • file1.txt
    • file2.txt
    • file3.pdf
    • file4.csv

Команды будут вести себя следующим образом:

~$ find-text
Path (dot for current): example-files/
Ext (unpunctured): txt

example-files/file1.txt
example-files/file2.txt


~$ rename-text
Path (dot for current): ./example-files
Ext (unpunctured): txt
Change by ext. (unpunctured): mp3

Found files:
./example-files/file1.txt
./example-files/file1.txt

Changed Files:
./example-files/file1.mp3
./example-files/file1.mp3
~$
person Pyetro    schedule 21.01.2021

Вы можете использовать инструмент, предназначенный для массового переименования файлов, например renamer.

Чтобы переименовать все расширения файлов в текущей папке:

$ renamer --find ".html" --replace ".txt" --dry-run * 

Еще много примеров использования можно найти здесь.

person Lloyd    schedule 01.05.2021

Самый простой способ - использовать rename.ul, который присутствует в большинстве дистрибутивов Linux.

rename.ul -o -v [oldFileExtension] [newFileExtension] [выражение для поиска файла для применения]

rename.ul -o -v .oldext .newext *.oldext

Параметры:

-o: не перезаписывать уже существующий .newext

-v: подробный

-n: сухой прогон

person CreatorGhost    schedule 10.07.2021