2009-07-10 3 views
80

У меня есть несколько каталогов и подкаталогов, содержащих файлы без расширения файла. Я хочу добавить .jpg ко всем файлам, содержащимся в этих каталогах. Я видел сценарии bash для изменения расширения файла, но не для его добавления. Он также должен быть рекурсивным, может кто-то помочь, пожалуйста?рекурсивно добавить расширение файла ко всем файлам

ответ

176

Альтернативная команда без явного цикла (man find):

find . -type f -exec mv '{}' '{}'.jpg \; 

Объяснение: рекурсивно находит все файлы (-type f), начиная с текущего каталога (.) и применяет команду перемещения (mv) к каждому из их. Обратите внимание также на цитаты около {}, так что имена файлов с пробелами (и даже с символами новой строки ...) должным образом обрабатываются.

+6

В частности, этот режим работает лучше, если в структуре каталога имеется огромное количество файлов (что приводит к тому, что bash расстраивается по поводу длины списка файлов для перебора). – DrAl

+0

@Al, если вы ссылаетесь на цикл 'for', который расстраивает bash для перебора списка файлов, это неверно. Цикл bash 'for' итеративно выдает каждую команду' mv'. – nik

+0

Вопрос: 'find' сначала настроил список файлов * до того, как он выполнил оператор' -exec'? Я так думаю, но хочу понять эту точку перед кодированием бесконечных циклов. – Boldewyn

4

как это,

for f in $(find . -type f); do mv $f ${f}.jpg; done 

Я не ожидал, что ты есть пробел в качестве разделителя имен файлов,
Если да, то имена должны быть обработаны немного.

Если вы хотите, чтобы выполнить команду из другой директории,
вы можете заменить find . с find /target/directory.

+1

Это не хватает 'do', и если в имени файла есть пробелы, то может быть лучше указать имя файла: для f в $ (find. -type f); do mv "$ f" "$ {f} .jpg"; сделал – DrAl

+0

и предположительно я запустил бы это из каталога верхнего уровня? – robjmills

+0

@seengee: да. Обратите внимание, что эта команда также пропускает тире в '-type'. – Stephan202

49

это найдет файлы без расширения и добавьте ваш .jpg

find /path -type f -not -name "*.*" -exec mv "{}" "{}".jpg \; 
+6

+1 потому что это пропускает файлы, у которых уже есть расширение. – Stephan202

+0

Это, безусловно, даст желаемый результат в 99% случаев. +1 – les

0

rename

не уверен, что он может переименовать файлы без расширений (я на окнах 7 прямо сейчас)

+1

он может, но он также переименует каталоги, и нет возможности сказать, что он рекурсивно работает в подкаталогах (по крайней мере, с версией, которую я имею на Ubuntu). – mirod

+0

Я знаю, по крайней мере, две разные команды под названием 'rename', одну программу C, включенную в util-linux-ng, и одну программу Perl (самой Стены) на машинах Debian нашего университета. На самом деле, ни одна из них не рекурсивно. – Boldewyn

9

Это немного поздно, но я подумал, что добавлю, что лучшее решение (хотя, возможно, менее читаемое), чем те, которые до сих пор могут быть:

find /path -type f -not -name "*.*" -print0 | xargs -0 rename 's/(.)$/$1.jpg/' 

Использование шаблона find | xargs обычно приводит к более эффективному выполнению, так как вам не нужно разветвлять новый процесс для каждого файла.

Обратите внимание, что для этого требуется версия переименования, найденная в дистрибутивах с расширением Debian (aka prename), а не традиционное переименование. Это всего лишь крошечный скрипт perl, поэтому было бы достаточно просто использовать команду выше в любой системе.

0

Для переименования всех файлов без расширения в ОС Windows Basic вы можете сделать ren * *.jpg Поскольку файл, как без расширения, просто используйте *, или если вы хотите изменить формат PNG в JPG использования ren *.png *.jpg