рекурсивно добавить расширение файла ко всем файлам


106

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

Ответы:


228

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

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

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


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

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

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

2
эта команда также найдет файлы с расширением. Это то, чего хочет OP?
ghostdog74

1
@ ghostdog74: Поскольку он принял этот ответ, очевидно, что сказанное выше помогло. В противном случае, как вы упомянули ниже, добавление -not -name "*.*"поможет.
Stephan202

62

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

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

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

9

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

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

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

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


4

как это,

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

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

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


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

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

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

Мне нужно было куда-то пойти и набрать слишком быстро ... сейчас поправляю.
nik

1

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


0

rename

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


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

Я знаю, по крайней мере, две разные команды rename, одна из которых - программа на языке C, включенная в util-linux-ng, а другая - программа Perl (созданная самим Уоллом) на машинах Debian нашего университета. На самом деле ни один из них не выполняет рекурсию.
Boldewyn
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.