파일 이름 접미사를 사용하여 다양한 크기의 축소판 만들기

파일 이름 접미사를 사용하여 다양한 크기의 축소판 만들기

나는 며칠 동안 이 문제와 씨름해 왔지만 StackExchange나 Google 검색에서 해결책을 찾지 못했습니다.

나는 다음과 같은 디렉터리 구조를 가지고 있습니다(실제로는 20,000개 이상의 파일이 있기 때문에 단순화되었습니다). 매년 각 달에 대한 디렉토리가 있습니다. 매달 매일의 디렉토리가 있습니다.

2017
  01
    01
    ...
    31
  ...
  12
2018
2019

다음 디렉터리에는 이미지가 있습니다.

123_43e6d929fcdbfa00aee1892893127b34.png
4567_24a847285bae9ddb6d3c33d237c6d481.jpg

내가 이루고 싶은 것

동일한 대상에 접미사가 포함된 각 파일의 축소판 버전(크기 조정 및 자르기)을 만들고 싶습니다. 따라서 위의 예는 다음과 같습니다.

123_43e6d929fcdbfa00aee1892893127b34.png
123_43e6d929fcdbfa00aee1892893127b34-120x160.png
123_43e6d929fcdbfa00aee1892893127b34-300x300.png
123_43e6d929fcdbfa00aee1892893127b34-800x800.png
4567_24a847285bae9ddb6d3c33d237c6d481.jpg
4567_24a847285bae9ddb6d3c33d237c6d481-120x160.jpg
4567_24a847285bae9ddb6d3c33d237c6d481-300x300.jpg
4567_24a847285bae9ddb6d3c33d237c6d481-800x800.jpg

내가 시도한 것

for file in *.jpg; do convert $file -set filename:base "%[base]" -resize 120x160^ -gravity center -extent 120x160 -quality 90\> "%[filename:base]-120x160.jpg"; done

우리가 반복하면서 새로운 이미지를 생성하기 때문에 이로 인해 약간의 루프가 발생한다고 생각합니다. 그래서 나는 수표를 추가하기 위해 PHP 스크립트를 만들고 다음과 같이 생각해 냈습니다.

foreach ($all_files as $file) {
    $path = $file->getPathname();

    $resized = str_replace_last('.', '-120x160.', $path);             
    if (preg_match('/\-\d{3}x\d{3}\./', $path) || file_exists($resized) || substr($path,-4) != '.jpg') continue;

    exec("convert \"$path\" -set filename:base \"%d/%[base]-120x160.jpg\" -resize 120x160^ -gravity center -extent 120x160 -quality 95\> \"%[filename:base]\";
          convert \"$path\" -set filename:base \"%d/%[base]-300x300.jpg\" -resize 300x300^ -gravity center -extent 300x300 -quality 95\> \"%[filename:base]\";
          convert \"$path\" -set filename:base \"%d/%[base]-800x800.jpg\" -resize 800x800^ -gravity center -extent 800x800 -quality 95\> \"%[filename:base]\"");
}

이것은 훌륭하게 작동하지만 66,000개의 썸네일을 모두 생성하고 서버 성능을 저하시키는 데는 시간이 오래 걸릴 것입니다. 아마도 대답이 될 것이라고 생각했지만 mogrify각 디렉토리에서 실행해야 하고 수천 개의 디렉토리가 있습니다.

누구든지 이를 달성할 수 있는 쉘, bash, PHP 등의 솔루션을 제안해 주시겠습니까?

감사해요

답변1

우리가 반복하면서 새로운 이미지를 생성하기 때문에 이로 인해 약간의 루프가 발생한다고 생각합니다.

아니요, 파일 목록이 생성된 다음 반복되므로 생성한 파일을 다시 처리하지 않습니다. 스크립트를 다시 실행할 때 파일을 다시 처리하지 않으려면 또 다른 문제입니다.

  • 엄지손가락을 제외하면 엄지손가락 처리를 피할 수 있습니다.부정 일치(또는 더 엄격한 긍정적 일치)
  • 그러나 엄지 손가락이 이미 있는 경우 파일 처리를 방지하기 위한 몇 가지 논리도 있어야 합니다(소스 이미지는 절대 업데이트되지 않는다고 가정합니다).

...하지만 내가 아는 한 이것은 PHP 코드가 수행하는 작업입니다.

이것은 훌륭하게 작동하지만 66,000개의 썸네일을 모두 생성하고 서버 성능을 저하시키는 데는 시간이 오래 걸릴 것입니다.

66K 파일에서 세 개의 엄지손가락을 생성하는 데는 실제로 시간이 좀 걸릴 것입니다. 하지만 무엇을 하든 각 엄지 손가락에 대해 크기 조정 및 재인코딩을 수행해야 하며 이로 인해 약간의 CPU가 필요합니다. 소스 파일을 세 번 읽지 않도록 계획할 수 있지만 Linux의 파일 캐싱이 이를 처리합니다.

프로세스가 서버를 많이 사용하지 않게 하려면 각 이미지(또는 매일 디렉터리) 뒤에 1-2초의 절전 명령을 추가할 수 있습니다.

답변2

Make를 사용한 예는 다음과 같습니다. 여기서의 장점은 이미 가지고 있는 것을 만들려고 하지 않는다는 것입니다. 그러니 잠시 실행했다가 중지했다가 나중에 시간이 나면 다시 실행해 보는 것이 안전합니다. -j 플래그를 지정할 수도 있습니다. 예를 들어 "make -j 4"는 한 번에 최대 4개의 CPU 코어를 사용합니다(더 빠르지만 더 많은 리소스를 사용하게 됩니다).

ifeq (${MAKELEVEL}, 0)
   # path to this Makefile
   mfile = Makefile
endif

subdirs = $(shell find * -type d -print -prune)
files = $(wildcard *.jpg) $(wildcard *.png)
thumbs = $(wildcard *-120x160.*) $(wildcard *-300x300.*) $(wildcard *-800x800.*)
notthumbs = ${basename $(filter-out $(thumbs), $(files) ) }
neededthumbs = $(foreach f, ${notthumbs}, ${f}-120x160.jpg ${f}-300x300.jpg ${f}-800x800.jpg)

all: thumbs recurse

thumbs: ${neededthumbs}

recurse:
        $(foreach f, ${subdirs}, $(MAKE) -C ${f} -f ../${mfile} mfile=../${mfile} all ; )

%-120x160.jpg: %.jpg
        echo convert $< -resize 120x160 $@
%-300x300.jpg: %.jpg
        echo convert $< -resize 300x300 $@
%-800x800.jpg: %.jpg
        echo convert $< -resize 800x800 $@
%-120x160.jpg: %.png
        echo convert $< -resize 120x160 $@
%-300x300.jpg: %.png
        echo convert $< -resize 300x300 $@
%-800x800.jpg: %.png
        echo convert $< -resize 800x800 $@

코드를 트리 루트에 있는 "Makefile"이라는 파일에 복사합니다(들여쓰기는 반드시 TABS여야 합니다! 알죠?). 해당 디렉토리로 cd하고 "make"(또는 "make -j 4" 등)를 입력합니다. 실행 속도를 느리게 하려면 "nice make"에서와 같이 "nice"를 사용할 수 있습니다.

관련 정보