Я пытаюсь использовать следующую команду:
ls -1d a/*.jpg | parallel convert -resize 300x300 {}'{=s/\..*//=}'.png
Однако одна проблема, которую мне не удалось решить, заключается в том, что файлы должны выводиться в папку b, а не в ту же папку.
Несколько раз искал ответ, но не нашел ни одного, где файлы передаются через команду ls. (тысячи фотографий). Я хотел бы сохранить те же инструменты (ls pipe, parallel и convert - или mogrify, если лучше)
Во-первых, с mogrify:
mkdir -p b # ensure output directory exists
magick mogrify -path b -resize 300x300 a/*.jpg
Это создает единый процесс mogrify, который обрабатывает все файлы без дополнительных затрат на создание нового процесса для каждого изображения. Скорее всего, это будет быстрее, если у вас небольшое количество изображений. Преимущество этого метода в том, что он не требует установки GNU Parallel. Недостатком является отсутствие параллелизма.
Во-вторых, с GNU Parallel:
mkdir -p b # ensure output directory exists
parallel --dry-run magick {} b/{/} ::: a/*.jpg
Здесь {/} означает «имя файла с удаленной частью каталога», и GNU Parallel делает все это просто и красиво для вас.
Если ваши изображения большие, скажем, 8-100 мегапикселей, определенно стоит использовать функцию JPEG «сжатие при загрузке», чтобы уменьшить нагрузку на дисковый ввод-вывод и память, например:
magick -define jpeg:size=512x512 ...
В приведенной выше команде.
Это создает новый процесс для каждого образа и, вероятно, будет быстрее, если у вас много ядер ЦП и много образов. Если у вас 12 ядер ЦП, все 12 будут заняты до тех пор, пока все ваши изображения не будут готовы — вы можете изменить количество или процент используемых ядер с помощью параметра -j. Небольшое снижение производительности заключается в том, что для каждого изображения создается новый процесс convert.
Вероятно, наиболее эффективным вариантом является использование GNU Parallel для параллелизма вместе с mogrify, чтобы амортизировать создание процесса для большего количества изображений, скажем, 32, например:
mkdir -p b
parallel -n 32 magick mogrify -path b -resize 300x300 ::: a/*.jpg
Примечание. Вам следует избегать разбора вывода ls, так как это может привести к ошибкам. Я имею в виду избегать этого:
ls file*.jpg | parallel
Вы должны предпочесть вводить имена файлов следующим образом:
parallel ... ::: file*.jpg
Примечание. Существует опция -X для GNU Parallel, которая немного эзотерична и, скорее всего, вступит в свои права только с сотнями/тысячами/миллионами изображений. Это позволит передать как можно больше имен файлов (с учетом ограничений длины командной строки) каждому процессу mogrify. И амортизируйте затраты на запуск процесса для большего количества файлов. Для 99% случаев использования ответы, которые я дал, должны быть достаточно производительными.
Примечание. Если ваша машина не имеет нескольких ядер, или ваши образы очень велики по сравнению с установленной оперативной памятью, или ваша дисковая подсистема работает медленно, ваш пробег будет варьироваться, и распараллеливание кода может оказаться нецелесообразным. Измерьте и посмотрите!
Привет, Марк, твой ответ потрясающий! Но та часть, которая меня изначально особенно интересовала, - это создание файлов в папке b, имя которой основано на папке a (например, a - это "что угодно", а b будет что угодно_200. В любом случае я решил это, используя файл .sh и передача папки в качестве аргумента. Я принимаю ваш ответ, поскольку он также, вероятно, намного лучше, чем передача ls! Большое спасибо!