Как запустить mogrify для 3 миллионов файлов JPG?

2160
Metin Çelik

У меня есть 3 миллиона файлов JPG, хранящихся на сервере Linux CentOS 6.

Я хочу изменить качество на% 50 размер файла более 1 мегабайта. Я написал эту команду, но получил ошибку «список аргументов слишком длинный»:

$ find -type f -name "*..jpg" -size +1M | xargs mogrify -quality 50 *.jpg bash: /usr/bin/xargs: Argument list too long 

Как я могу изменить качество миллионов файлов?

1
Почему вы добавляете `* .jpg` к` xargs`? Он получит файлы из `find`. choroba 10 лет назад 2

3 ответа на вопрос

2
Dennis Kaarsemaker

xargs supports a -n argument to limit the amount of arguments passed to whatever it calls:

find -type f -name '*.jpg' -size +1M -print0 | xargs -0 -n1 mogrify -quality 50 

This will launch mogrify once per image. As mogrify can only process one file at the time, this is the way to go.

Документация `mogrify` показывает примеры с` * .jpg`. choroba 10 лет назад 0
Ах, я слепо доверял man-странице: «SYNOPSIS mogrify [options] input-file» - указывая, что он поддерживает только одну. Dennis Kaarsemaker 10 лет назад 0
1
choroba

When using find and xargs, you don't need to name the files for xargs. It will get the list of files from find:

find -print0 -type f -name '*.jpg' -size +1M | xargs -0 -n100 mogrify -quality 50 

-n100 will process the images by 100s. -print0 and -0 will make the pipe work even if the filenames contain whitespace.

You can also call mogrify directly from find, ideally if it supports the + ending for exec:

find -type f -name '*.jpg' -size +1M -exec mogrify -quality 50 {} + 
Это все равно сделает список аргументов слишком длинным в первой команде, если все они передаются в xargs за одну. Кроме того, вы должны передать из `find` в` xargs` с помощью `find ... -print0 | xargs -0`. slhck 10 лет назад 0
Что ж, к счастью, `find` * может все это сделать *. : D Вместо завершения команды -exec с помощью `+`, ее также можно завершить с помощью `;`. Это выполняет команду один раз для каждого результата. Не забудьте убежать `;`! Daniel B 10 лет назад 0
@DanielB: В чем преимущество `;` перед `+` в этом случае? choroba 10 лет назад 0
Это не приводит к слишком длинной командной строке. Хотя `find` может уже обойти это, кто знает. Это также подходит для команд, которые не принимают пакетный ввод. Daniel B 10 лет назад 1
Ну, хотя это может быть немного спамом, я обнаружил, что `xargs` и` find`, на самом деле, достаточно умны, чтобы автоматически разбивать коллекцию аргументов. Daniel B 10 лет назад 0
0
Franck Dernoncourt

Кроссплатформенное решение с Python + convert: оно будет преобразовывать все PDF-файлы текущего каталога в PNG-файлы (вы можете изменить на JPG, если хотите) многопоточно.

from __future__ import print_function import os import glob import multiprocessing   def convert_to_png(pdf_filepath): ''' Convert PDF file to PNG file ''' png_filepath = '.png'.format(pdf_filepath[:-4]) print('pdf_filepath: '.format(pdf_filepath)) print('png_filepath: '.format(png_filepath)) command = 'convert -background white -alpha off -geometry 1600x1600 -density 200x200 -quality 100 -resize 800x '.format(pdf_filepath, png_filepath) print(command) os.system(command)  def main(): pdf_filepaths = glob.iglob(os.path.join('.','*.pdf')) pool = multiprocessing.Pool(processes=4) pool.map(convert_to_png, pdf_filepaths) pool.close() pool.join()  print('done')  if __name__ == "__main__": main() #cProfile.run('main()') # if you want to do some profiling 

Для этого требуется установить Imagemagick и Ghostscript . Работает на Linux / Mac OS X / Microsoft Windows.

Если вы предпочитаете добавлять имя файла на каждое изображение, вы можете заменить команду convert_to_png()на:

command = 'convert -background white -alpha off -geometry 1600x1600 -density 200x200 -quality 100 -annotate +50+50 -resize 800x '.format(pdf_filepath, png_filepath, os.path.basename(pdf_filepath)) 

(См. -Аннотировать документацию)

Похожие вопросы