私はこの問題と数日間戦ってきましたが、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、これを達成できるものは何ですか?
ありがとう
ループしながら新しいイメージを作成しているため、これにより少しループが発生すると思います。
いいえ、ファイルのリストが作成されてから繰り返されるため、作成したファイルを再処理する必要はありません。スクリプトを再実行した場合にファイルの再処理を回避したい場合は、別の問題です。
...しかし、私が知る限り、これはあなたがPHPコードが行うことです。
これはうまく機能しますが、66,000のサムネイルをすべて作成し、サーバーのパフォーマンスを低下させるには、永遠に時間がかかります。
66Kファイルから3つの親指を作成するには、確かに時間がかかります。しかし、何をするにしても、親指ごとにスケーリングと再エンコードを実行する必要があります。これにより、CPUがいくらか必要になります。ソースファイルを3回読み取らないようにすることも考えられますが、Linuxのファイルキャッシュがそれを処理します。
プロセスがサーバーを占有したくない場合は、各イメージ(または毎日のディレクトリ)の後に1〜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-j4」など)と入力します。実行速度を遅くするには、「Nicemake」のように「Nice」を使用します。