Perintah untuk resize gambar cukup singkat. Yang perlu diperhatikan saat memproses banyak file adalah bagaimana hasilnya disimpan. Jika hasil langsung menimpa gambar asli, kegagalan di tengah proses bisa menyisakan koleksi yang baru diproses sebagian. Menaruh semua hasil dalam satu folder juga berisiko menimbulkan benturan nama: events/photo.jpg dan products/photo.jpg akan memiliki nama file tujuan yang sama.
Direktori hasil yang terpisah menghindari kedua masalah tersebut. Script berikut menerima direktori sumber, direktori tujuan, dan batas panjang sisi gambar. File JPEG, PNG, serta WebP diproses secara rekursif dengan struktur folder dan format tetap dipertahankan, sementara file asli tidak diubah.
Pisahkan direktori hasil dari sumber
Jika sumbernya photos/events/photo.jpg, hasilnya akan tersimpan sebagai resized/events/photo.jpg ketika resized dipilih sebagai direktori tujuan. Script menolak direktori hasil yang berada di dalam direktori sumber agar hasil proses sebelumnya tidak ikut ditemukan pada eksekusi berikutnya. File yang sudah ada di direktori tujuan dilewati, bukan ditimpa.
ImageMagick 7 menyediakan perintah magick. Contoh ini juga memakai Bash dan utilitas GNU (find, realpath, mktemp, dan mv). Periksa magick -version terlebih dahulu; beberapa sistem masih menyediakan ImageMagick 6 dengan nama perintah berbeda.
Script pemrosesan massal
Simpan kode berikut sebagai batch-resize.sh:
#!/usr/bin/env bash
set -euo pipefail
if (( $# != 3 )); then
printf 'Usage: %s SOURCE_DIR OUTPUT_DIR MAX_EDGE\n' "$0" >&2
exit 2
fi
for tool in magick find realpath mktemp; do
if ! command -v "$tool" >/dev/null 2>&1; then
printf 'Missing command: %s\n' "$tool" >&2
exit 1
fi
done
if [[ ! -d "$1" || ! "$3" =~ ^[1-9][0-9]*$ ]]; then
printf 'Provide an existing source directory and a positive MAX_EDGE.\n' >&2
exit 2
fi
source=$(realpath -e -- "$1")
output=$(realpath -m -- "$2")
if [[ "$output" == "$source" || "$output" == "$source/"* ]]; then
printf 'The output directory must be outside the source directory.\n' >&2
exit 2
fi
mkdir -p -- "$output"
output=$(realpath -e -- "$output")
manifest=$(mktemp -- "$output/.resize-list.XXXXXXXX")
tmp=''
cleanup() {
if [[ -n "$tmp" ]]; then rm -f -- "$tmp"; fi
rm -f -- "$manifest"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
find "$source" -type f \( \
-iname '*.jpg' -o -iname '*.jpeg' -o \
-iname '*.png' -o -iname '*.webp' \
\) -print0 > "$manifest"
resized=0
skipped=0
failed=0
while IFS= read -r -d '' input; do
relative=${input#"$source"/}
target="$output/$relative"
if [[ -e "$target" || -L "$target" ]]; then
((skipped += 1))
continue
fi
parent=${target%/*}
mkdir -p -- "$parent"
extension=${target##*.}
tmp=$(mktemp -- "$parent/.resize.XXXXXXXX.$extension")
if magick "${input}[0]" -auto-orient -resize "${3}x${3}>" "$tmp"; then
mv -n -- "$tmp" "$target"
if [[ -e "$tmp" ]]; then
rm -f -- "$tmp"
((skipped += 1))
else
((resized += 1))
fi
else
rm -f -- "$tmp"
((failed += 1))
printf 'Failed: %q\n' "$relative" >&2
fi
tmp=''
done < "$manifest"
printf 'Resized: %d | skipped: %d | failed: %d\n' \
"$resized" "$skipped" "$failed"
(( failed == 0 ))Untuk koleksi gambar dengan sisi terpanjang maksimal 1600 piksel:
chmod +x batch-resize.sh
./batch-resize.sh ./photos ./resized 1600Argumen ketiga adalah batas ukuran, bukan lebar dan tinggi yang harus selalu sama. Gambar 4000 × 3000 akan menjadi 1600 × 1200, sedangkan gambar 900 × 600 tidak diperbesar.
Mengapa penanganan file perlu diperhatikan
Aturan geometri resize ImageMagick 1600x1600> mempertahankan rasio aspek dan hanya mengecilkan gambar bila diperlukan. Karakter > harus berada di dalam tanda kutip agar shell tidak menganggapnya sebagai pengalihan output. Opsi -auto-orient menerapkan orientasi EXIF sebelum resize jika informasi tersebut tersedia.
find -print0 dan read -d '' menggunakan pemisah NUL untuk mengirim nama file. Foto bernama holiday trip.jpg, bahkan nama file yang mengandung baris baru, tetap diproses sebagai satu path. Manifest juga membuat kegagalan find menghentikan pekerjaan sebelum konversi dimulai; kesalahan penelusuran direktori tidak tersembunyi di dalam process substitution. Rujuk dokumentasi GNU findutils tentang nama file.
Setiap gambar lebih dahulu ditulis ke file sementara di direktori tujuannya, lalu dipindahkan ke nama akhir setelah ImageMagick berhasil. Ekstensi pada file sementara membantu ImageMagick mengenali format hasil. mv -n mencegah penimpaan file tujuan yang muncul saat proses berlangsung. Script masih memeriksa apakah file sementara tersisa karena GNU mv -n dapat melaporkan keberhasilan meskipun melewati file yang sudah ada. Jika konversi gagal, file sementara dihapus, jumlah kegagalan bertambah, dan gambar berikutnya tetap diproses. Status akhir script menandakan kegagalan jika ada konversi yang tidak berhasil.
Batasan sebelum memproses banyak gambar
Penanda [0] pada input sengaja memilih frame pertama. WebP animasi akan menghasilkan gambar diam, bukan animasi yang di-resize. Ekstensi hanya dipakai untuk memilih kandidat; ekstensi tersebut tidak menjamin isi file valid, sehingga ImageMagick dapat menolak file yang salah format atau rusak.
Meskipun > mencegah pembesaran, ImageMagick tetap melakukan decode dan encode ulang pada gambar yang sebenarnya sudah cukup kecil. Proses encode ulang JPEG dapat mengubah kualitasnya. Metadata dan profil warna juga perlu diperiksa jika keduanya penting untuk arsip. Script ini memproses gambar satu per satu agar tidak menjalankan terlalu banyak decoder secara bersamaan, tetapi satu gambar beresolusi sangat tinggi tetap dapat memakai memori dalam jumlah besar.
Pada eksekusi berikutnya, file yang sudah ada di direktori tujuan akan dilewati. Mekanisme ini berguna untuk melanjutkan pekerjaan yang terputus, tetapi perubahan batas ukuran tidak akan memperbarui hasil lama. Gunakan direktori hasil baru ketika ukuran atau kebutuhan encoding berubah.