Как переименовать расширение для пакета файлов?
В каталоге у меня есть куча *.html
файлы.
Я хотел бы переименовать их всех в *.txt
Я использую оболочку bash.
28 ответов
Для лучшего решения (с использованием только функций bash, в отличие от внешних вызовов) см. Один из других ответов.
Следующее будет делать и не требует, чтобы система имела rename
программа (хотя вы бы чаще всего имели это в системе):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
РЕДАКТИРОВАТЬ: Как указано в комментариях, это не работает для имен файлов с пробелами в них без надлежащего цитирования (теперь добавлено выше). Когда вы работаете исключительно с вашими собственными файлами, у которых, как вы знаете, нет пробелов в именах файлов, это будет работать, но всякий раз, когда вы пишете что-то, что может быть использовано позднее, не пропускайте правильное цитирование.
Если вы используете bash, вам не нужны внешние команды, такие как sed, basename, rename, expr и т. Д.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
rename 's/\.html$/\.txt/' *.html
делает именно то, что вы хотите.
Это работало для меня на OSX от.txt до.txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
Вы хотите использовать rename
:
rename -S .html .txt *.html
Это именно то, что вы хотите - это изменит расширение от .html
в .txt
для всех подходящих файлов *.html
,
Примечание: Грег Хьюгилл правильно указывает, что это не встроенная команда bash; и это отдельная команда Linux. Если вам просто нужно что-то в Linux, это должно работать нормально; если вам нужно что-то более кроссплатформенное, взгляните на один из других ответов.
На Mac...
- Установите переименовать, если у вас нет:
brew install rename
rename -S .html .txt *.html
Это самое приятное решение, которое я нашел, которое работает на OSX и Linux, и оно прекрасно работает и с git!
find . -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".tsx' - '{}' \;
и с мерзавцем:
find . -name "*.js" -exec bash -c 'git mv "$1" "${1%.js}".tsx' - '{}' \;
В этом вопросе явно упоминается Bash, но если у вас есть ZSH, это довольно просто:
zmv '(*).*' '$1.txt'
Если вы получаете zsh: command not found: zmv
затем просто запустите:
autoload -U zmv
А потом попробуйте еще раз.
Спасибо этой оригинальной статье за совет о ZMV.
В Linux или git bash окна или wsl окна попробуйте команду ниже, чтобы изменить расширение каждого файла в текущем каталоге или подкаталогах или даже их подкаталогах с помощью всего одной строки кода
find . -depth -name "*.html" -exec sh -c 'mv "$1" "${1%.html}.txt"' _ {} \;
Вот пример команды переименования:
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
Одна строка, без петель:ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
cbongiorno@ip-172-31-26-242:~/pgsql$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json ac8453e2-0d82-4d43-b80e-205edb754700.json
cbongiorno@ip-172-31-26-242:~/pgsql$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
cbongiorno@ip-172-31-26-242:~/pgsql$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt ac8453e2-0d82-4d43-b80e-205edb754700.txt
cbongiorno@ip-172-31-26-242:~/pgsql$
Командаmmv
похоже, очень эффективно справляется с этой задачей на огромном количестве файлов (десятки тысяч в секунду). Например, переименовать все .xml
файлы в .html
файлы, используйте это:
mmv ";*.xml" "#1#2.html"
;
будет соответствовать пути, *
будет соответствовать имени файла, и они называются #1
а также #2
в названии замены.
Ответы на основе exec
или каналы были слишком медленными или не работали с очень большим количеством файлов.
После сканирования чужого веб-сайта я обнаружил, что тысячи файлов не имеют расширения.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"
Нужно исправить, хотя: работа с пробелами в именах файлов
Переименуйте расширения файлов для всех файлов в текущем каталоге и подкаталогах без каких-либо других пакетов (используйте только сценарий оболочки):
Создать сценарий оболочки
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
Это хороший способ изменить несколько расширений одновременно:
for fname in *.{mp4,avi}
do
mv -v "$fname" "${fname%.???}.mkv"
done
Примечание: будьте осторожны, чтобы размер расширения был одинаковым (???)
Попробуй это
rename .html .txt *.html
использование:
rename [find] [replace_with] [criteria]
Подобно тому, что предлагалось ранее, я сделал это следующим образом:
find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;
Сначала я проверил
find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
Самый простой способ - использовать
rename.ul
он присутствует в большинстве дистрибутивов Linux
rename.ul -o -v [oldFileExtension] [newFileExtension] [выражение для поиска файла для применения]
rename.ul -o -v .oldext .newext *.oldext
Параметры:
-o: не перезаписывать уже существующий .newext
-v: подробный
-n: сухой прогон
Немного опоздал на вечеринку. Вы можете сделать это с помощью 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' - {}
Красиво и просто!
find . -iname *.html -exec mv {} "$(basename {} .html).text" \;
Если вы предпочитаете PERL, существует короткий сценарий PERL (изначально написанный Ларри Уоллом, создателем PERL), который будет делать именно то, что вы хотите здесь: http://tips.webdesign10.com/files/rename.pl.txt. Для вашего примера следующее должно сделать трюк
rename.pl 's/html/txt/' *.html
знак равно
(Спасибо @loretoparisi за обновленный URL)
Вы также можете создать функцию в Bash, добавить ее в .bashrc
или что-то еще, а затем используйте его, где хотите.
change-ext() {
for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}
Применение:
change-ext css scss
Источник кода в функции: /questions/31221688/kak-pereimenovat-rasshirenie-dlya-paketa-fajlov/31221689#31221689
К сожалению, это не тривиально, чтобы сделать портативно. Вам, вероятно, нужно немного опыта магии.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Уберите эхо, как только вы будете счастливы, он сделает то, что вы хотите.
Редактировать: basename
вероятно, немного более читабельным для этого конкретного случая, хотя expr
в целом более гибкий
Вот что я использовал для переименования .edge
файлы в .blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Работает как шарм.
Вот решение, использующее AWK. Убедитесь, что файлы находятся в рабочем каталоге. В противном случае перейдите в каталог, в котором расположены файлы html, а затем выполните следующую команду:
for i in $(ls | grep .html); do j=$(echo $i | grep -oh "^\w*." | awk '{print $1"txt"}'); mv $i $j; done
I wrote this code in my .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";'
In a folder like "/home/<user>/example-files" having this structure:
- /home/<user>/example-files:
- file1.txt
- file2.txt
- file3.pdf
- file4.csv
The commands would behave like this:
~$ 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
~$