Ответы:
Для лучшего решения (с использованием только функций 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 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
В случае с 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