Ответы:
Для лучшего решения (с использованием только функций bash, в отличие от внешних вызовов) см. Один из других ответов .
Следующее будет делать и не требует, чтобы система имела renameпрограмму (хотя чаще всего это было бы в системе):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
РЕДАКТИРОВАТЬ: Как указано в комментариях, это не работает для имен файлов с пробелами в них без надлежащего цитирования (теперь добавлено выше). Когда вы работаете исключительно с вашими собственными файлами, у которых, как вы знаете, нет пробелов в именах файлов, это будет работать, но всякий раз, когда вы пишете что-то, что может быть использовано позже, не пропускайте правильное цитирование.
ren *.a *.b
$()вместо устаревшего синтаксиса обратного ключа. Улучшает читабельность и делает синтаксис намного менее двусмысленным, когда у вас есть символы, которые необходимо экранировать от обратной косой черты, чтобы быть буквальными внутри подстановки команд последней.
Если вы используете bash, вам не нужны внешние команды, такие как sed, basename, rename, expr и т. Д.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
"${file%.*}.txt", но это может быть опасно для файлов без расширения вообще.
$внутри фигурных скобок нет!
--«operator»: mv - «$ file» «$ {file% .html} .txt» Этот оператор предотвращает имена файлов, начинающиеся с '-' от анализа 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.
Примечание: Грег Хьюгилл правильно указывает, что это не встроенная команда bash; и это отдельная команда Linux. Если вам просто нужно что-то в Linux, это должно работать нормально; если вам нужно что-то более кроссплатформенное, взгляните на один из других ответов.
renameпрограмма не связана bashи не доступна на всех платформах. Я видел это только в Linux.
rename -S .html .text *.htmlгде -Sрасшифровывается--subst-all
На Mac ...
brew install renamerename -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
В случае с OP я мог бы немного изменить это, чтобы переименовывать только файлы * .txt, например так:
find . -xtype f -iname *.txt -exec filename="{}" mv -iv ${filename%.*}.{txt,html} \;
Разбитый (время молотка!):
-iname * .txt
- означает, что ТОЛЬКО файлы, заканчивающиеся на .txt
mv -iv "{}. {txt, html}" - Когда find передает {} в качестве имени файла, $ {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
К сожалению, это не тривиально, чтобы сделать портативно. Вам, вероятно, нужно немного опыта магии.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Уберите эхо, как только вы будете счастливы, он сделает то, что вы хотите.
Edit: 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