рекурсивно додавати розширення файлу до всіх файлів


106

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

Відповіді:


228

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

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

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


7
Зокрема, цей працює краще, якщо в структурі каталогу є величезна кількість файлів (змушує баш засмучуватися з приводу довжини списку файлів, щоб повторити його).
DrAl

@Al, якщо ви посилаєтесь на forцикл, який засмучує bash, щоб повторити список файлів, це невірно. Цикл bash forітеративно видає кожну mvкоманду.
nik

Запитання: findСпочатку встановлює список файлів перед його виконанням -exec? Я думаю, що так, але хочу зрозуміти цю точку перед кодуванням нескінченних циклів.
Boldewyn

2
ця команда також знайде файли з розширенням. Це те, чого хоче ОП?
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 (aka prename), а не традиційне перейменування. Це просто крихітний сценарій Perl, тому було б досить просто використовувати команду, що була вище, в будь-якій системі.


4

подобається це,

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

Я не чекаю, що у вас є пробіли, розділені на простір, імена,
якщо це зробити, імена потрібно буде трохи обробити.

Якщо ви хочете , щоб виконати команду з іншого каталогу,
ви можете замінити find .з find /target/directory.


1
У цьому відсутньому значенні "робити", і якщо у імені файлу є пробіли, можливо, краще навести ім'я файлу: for f в $ (знайти. -Типу f); do mv "$ f" "$ {f} .jpg"; зроблено
DrAl

і, мабуть, я би запускав це з каталогу верхнього рівня?
robjmills

@seengee: так. Зауважте, що ця команда також пропускає тире в -type.
Stephan202

Мені довелося кудись поїхати і надрукувати надто швидко ... виправлення зараз.
nik

1

Для перейменування всіх файлів без розширення в основний Windows ви можете зробити. ren * *.jpg Оскільки файл не є розширенням, просто використовуйте *, або якщо ви хочете змінити png на використання jpgren *.png *.jpg


0

rename

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


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

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