Bab 13 sudah membekali kita dengan empat pola otomatisasi harian: rename massal, backup, organisasi file, dan alias/function permanen. Bab ini melanjutkan arah yang sama dengan fokus lebih spesifik ke jenis file yang paling sering bikin folder User penuh sesak, yaitu foto dan video. Koleksi hasil jepretan kamera HP atau footage hasil rekam layar cepat menumpuk dalam format dan ukuran yang tidak seragam, dan merapikannya satu per satu lewat aplikasi GUI jelas tidak praktis untuk ratusan file sekaligus. Bab ini membahas tiga kebutuhan inti: konversi dan resize batch gambar/video lewat ffmpeg dan ImageMagick, kompresi/ekstraksi arsip lewat tar, zip, dan gzip, ditutup studi kasus script organizer yang menggabungkan semuanya untuk merapikan koleksi media secara otomatis.
14.1 Konversi Batch Gambar dan Video
Sub-bab ini membahas cara mengonversi dan meng-resize banyak file gambar atau video sekaligus lewat dua tool eksternal paling umum dipakai untuk kebutuhan ini: ffmpeg untuk video/audio, dan ImageMagick untuk gambar.
14.1.1 Instalasi ffmpeg dan ImageMagick
ffmpeg dan ImageMagick bukan bagian dari Bash maupun coreutils bawaan sistem, jadi keduanya perlu dipasang secara terpisah lewat package manager sebelum bisa dipakai di script. Sesuai konteks distro yang sudah ditegaskan di Bab 1.3, cara pemasangannya berbeda-beda tergantung sistem yang dipakai.
# Debian/Ubuntu
sudo apt update && sudo apt install ffmpeg imagemagick
# Fedora
sudo dnf install ffmpeg imagemagick
# Arch Linux
sudo pacman -S ffmpeg imagemagick
# macOS (lewat Homebrew, Bab 1.3.2)
brew install ffmpeg imagemagickVerifikasi pemasangan lewat opsi versi masing-masing tool sebelum lanjut ke langkah praktik berikutnya.
ffmpeg -version
magick -version # ImageMagick 7
convert -version # ImageMagick 6Perbedaan magick dan convert di atas bukan salah ketik. ImageMagick versi 6 menyediakan beberapa perintah terpisah seperti convert, mogrify, dan identify, sedangkan ImageMagick versi 7 menyatukan semuanya di bawah satu perintah payung magick. Perintah convert di ImageMagick 7 masih berfungsi untuk kompatibilitas mundur, tapi sudah berstatus deprecated dan memunculkan pesan peringatan setiap dipakai, menurut pembahasan resmi tim ImageMagick sendiri. Karena distro stabil seperti Ubuntu 22.04 LTS atau Debian 11/12 masih memaketkan ImageMagick 6, sementara instalasi lebih baru (termasuk lewat Homebrew di macOS) umumnya sudah ImageMagick 7, script yang portable sebaiknya mendeteksi dulu perintah mana yang tersedia, alih-alih mengasumsikan salah satunya.
if command -v magick &> /dev/null; then
IM_CONVERT="magick"
IM_MOGRIFY="magick mogrify"
else
IM_CONVERT="convert"
IM_MOGRIFY="mogrify"
fiBuiltin command -v di atas, menurut GNU Bash Reference Manual, memeriksa apakah sebuah nama dikenali sebagai perintah tanpa benar-benar menjalankannya, dan tidak menampilkan apa pun kalau tidak ditemukan, cocok dipasangkan dengan pengujian exit status lewat operator &&/|| dari Bab 6.4.2. Pola deteksi versi ini akan dipakai lagi di studi kasus 14.3.
14.1.2 Konversi Batch Video dengan ffmpeg
Sintaks paling dasar ffmpeg, menurut dokumentasi resminya, adalah ffmpeg -i input output: ffmpeg otomatis mendeteksi format input, dan menebak format output dari ekstensi nama file tujuan. Menggabungkan sintaks ini dengan for loop dari Bab 7.1 mengonversi seluruh video dalam satu folder sekaligus.
#!/bin/bash
for file in *.mov; do
[[ -f "$file" ]] || continue
ffmpeg -n -i "$file" -c:v libx264 -crf 23 -c:a aac "${file%.mov}.mp4"
done${file%.mov} memotong ekstensi .mov dari nama file lewat parameter expansion yang sama seperti Bab 13.1.2, lalu .mp4 ditempelkan sebagai ekstensi baru pada nama file output. Opsi -c:v libx264 memilih codec, komponen yang menentukan cara data video dikompresi dan didekompresi, dalam hal ini video H.264 lewat pustaka libx264, dan -c:a aac memilih codec audio AAC, kombinasi yang kompatibel luas di berbagai pemutar video modern. Opsi -crf 23 (Constant Rate Factor) mengatur keseimbangan kualitas dan ukuran file untuk libx264: skalanya 0 sampai 51, makin kecil angkanya makin tinggi kualitasnya sekaligus makin besar ukuran filenya, dengan 23 sebagai nilai default kalau opsi ini tidak disertakan sama sekali.
Opsi -n di depan -i pada contoh di atas bukan sekadar kebiasaan aman seperti mv -n di Bab 13.1.4, tapi krusial untuk script yang berjalan tanpa pengawasan. Secara default, kalau file output sudah ada, ffmpeg menampilkan prompt interaktif Overwrite? [y/N] dan menunggu jawaban dari stdin. Di dalam for loop yang dijalankan lewat script tanpa terminal interaktif, prompt ini bisa membuat proses seolah menggantung tanpa progres jelas. Opsi -n membuat ffmpeg langsung melewati file yang outputnya sudah ada tanpa bertanya, sedangkan opsi -y adalah kebalikannya, langsung menimpa tanpa bertanya. Salah satu dari keduanya wajib eksplisit ditulis di setiap script batch, jangan mengandalkan perilaku default.
Kalau tujuannya sekadar mengganti container format tanpa mengubah kualitas maupun ukuran video sama sekali, misalnya dari .mkv ke .mp4, opsi -c:v copy -c:a copy melakukan stream copy: menyalin data video dan audio apa adanya tanpa proses encoding ulang, jauh lebih cepat dibanding mengonversi ulang codec-nya.
for file in *.mkv; do
[[ -f "$file" ]] || continue
ffmpeg -n -i "$file" -c:v copy -c:a copy "${file%.mkv}.mp4"
done14.1.3 Resize dan Konversi Batch Gambar
Untuk gambar, ImageMagick menyediakan dua pendekatan berbeda: convert/magick yang menulis hasilnya ke file baru, dan mogrify yang langsung memodifikasi file aslinya di tempat. Perbedaan ini penting dipahami sebelum dipraktikkan karena menyangkut risiko kehilangan file asli.
# Menulis ke file baru (aman, tidak menyentuh file asli)
magick foto.png -resize 1920x1080 foto-kecil.jpg
# Mengubah file asli langsung, tanpa salinan cadangan
mogrify -resize 1920x1080 foto.pngMenurut dokumentasi resmi ImageMagick, mogrify memang dirancang untuk menimpa file sumbernya langsung, sedangkan convert (atau magick tanpa subperintah di versi 7) menulis ke file tujuan yang terpisah. Karena sifatnya yang destruktif itu, mogrify menyediakan opsi -path untuk mengarahkan hasilnya ke folder lain, dan opsi -format untuk sekaligus mengubah ekstensi output, kombinasi yang membuat file asli tetap utuh.
mkdir -p hasil-resize
mogrify -path hasil-resize -format jpg -resize 1920x1080 *.pngPerintah di atas membaca semua .png di folder saat ini, meng-resize-nya ke maksimal 1920x1080 piksel sambil mempertahankan rasio aspek (perilaku default geometri resize ImageMagick kalau tidak diberi tanda ! di akhir ukuran), lalu menyimpan hasilnya sebagai .jpg baru di folder hasil-resize, tanpa mengubah file .png aslinya sama sekali. Kebiasaan yang aman untuk operasi batch semacam ini sama seperti prinsip dry-run di Bab 13.1.4: coba dulu di salinan folder kecil berisi beberapa file sampel, baru dijalankan ke seluruh koleksi asli setelah hasilnya sesuai harapan.
14.1.4 Rename Otomatis Saat Konversi
Konversi batch adalah momen yang pas untuk sekaligus merapikan nama file, menggabungkan teknik for loop di 14.1.2/14.1.3 dengan parameter expansion dari Bab 13.1.2 dan command substitution date dari Bab 13.2.3.
#!/bin/bash
tanggal="$(date +%Y%m%d)"
for file in *.mov; do
[[ -f "$file" ]] || continue
nama_dasar="${file%.mov}"
ffmpeg -n -i "$file" -c:v libx264 -crf 23 -c:a aac "${tanggal}_${nama_dasar}.mp4"
donePola ${tanggal}_${nama_dasar}.mp4 di atas menambahkan awalan tanggal konversi ke setiap file hasil, mempermudah pengurutan kronologis di file manager mana pun tanpa perlu membuka satu per satu untuk melihat tanggal aslinya. Kalau nama file sumber mengandung spasi atau karakter tidak konsisten, sisipkan dulu langkah normalisasi lewat sed seperti dibahas di Bab 13.1.3 sebelum nama itu dipakai sebagai nama file output.
14.1.5 Troubleshooting Format Tidak Didukung
Format foto .heic, format default kamera iPhone sejak iOS 11, sering jadi jebakan tersembunyi untuk ImageMagick. Menurut catatan isu di repositori resmi GitHub Homebrew, dukungan HEIC bergantung pada pustaka delegasi libheif, yang tidak selalu ikut terpasang tergantung sumber instalasinya: paket imagemagick resmi di repositori Ubuntu/Debian historisnya tidak selalu menyertakan libheif secara default, sedangkan formula imagemagick di Homebrew untuk macOS saat ini sudah menjadikan libheif sebagai dependency standar. Cek dulu dukungan sebuah format sebelum diandalkan di script produksi, jangan berasumsi begitu saja.
magick -list format | grep -i heic # ImageMagick 7
identify -list format | grep -i heic # ImageMagick 6Kalau kedua perintah di atas tidak menampilkan apa pun, dukungan HEIC memang belum tersedia di instalasi yang sedang dipakai. Di Linux, opsi paling praktis adalah memasang libheif lewat repositori tambahan distro (misalnya PPA pihak ketiga untuk Ubuntu versi lama) atau memakai rilis distro yang lebih baru yang sudah memaketkannya, alih-alih mengompilasi ulang ImageMagick dari source sendiri. Script yang mengonversi format seperti ini sebaiknya juga tidak berasumsi konversi selalu berhasil; exit status $? dari Bab 6.4.1 setelah pemanggilan magick/mogrify bisa dipakai untuk mendeteksi kegagalan lebih dini, daripada baru sadar filenya gagal terkonversi setelah seluruh proses batch selesai.
14.2 Kompresi dan Ekstraksi Arsip
Sub-bab ini membahas tiga tool kompresi/arsip yang saling melengkapi: gzip untuk kompresi satu file, zip/unzip untuk arsip yang mudah dibagikan lintas sistem operasi, dan tar untuk ekstraksi arsip yang sudah diperkenalkan sisi pembuatannya di Bab 13.2.3.
14.2.1 gzip untuk Kompresi File Tunggal
gzip berbeda dari tar: gzip hanya mengompresi satu file per operasi dan tidak bisa menggabungkan banyak file jadi satu arsip seperti tar, itu sebabnya kombinasi tar + gzip (opsi -z di Bab 13.2.3) begitu umum dipakai untuk mengarsipkan seluruh folder.
gzip foto-mentah.rawPerlu dicatat baik-baik, perilaku default gzip menurut dokumentasi resminya bersifat destruktif: gzip otomatis menghapus file asli foto-mentah.raw dan menggantikannya dengan foto-mentah.raw.gz, tanpa konfirmasi maupun salinan cadangan. Kalau kita masih ingin mempertahankan file aslinya, tambahkan opsi -k (--keep).
gzip -k foto-mentah.rawMengembalikan file terkompresi ke bentuk semula memakai opsi -d (--decompress), atau perintah gunzip yang setara.
gzip -d foto-mentah.raw.gz
# setara dengan:
gunzip foto-mentah.raw.gz14.2.2 zip dan unzip Lintas Platform
zip mengemas banyak file sekaligus jadi satu arsip seperti tar, tapi punya kelebihan format yang bisa dibuka native tanpa tool tambahan apa pun di Windows maupun macOS, membuatnya pilihan lebih aman dibanding .tar.gz saat arsip perlu dibagikan ke pengguna yang tidak familiar dengan terminal Linux. Sama seperti ffmpeg dan ImageMagick, zip/unzip juga bukan bagian bawaan Bash dan perlu dipasang terpisah lewat package manager kalau belum tersedia (sudo apt install zip unzip di Debian/Ubuntu, menyesuaikan untuk distro lain seperti di 14.1.1).
zip -r dokumen-penting.zip ~/Dokumen/Opsi -r (recursive) wajib disertakan untuk mengarsipkan seluruh isi folder beserta subfoldernya; tanpa -r, zip hanya akan mengeluh kalau argumennya berupa folder. Melihat isi arsip tanpa benar-benar mengekstraknya, kebiasaan verifikasi yang sama seperti tar -t di Bab 13.2.4, memakai opsi -l.
unzip -l dokumen-penting.zipSaat mengekstrak, kalau ada file di dalam arsip yang namanya sudah ada di folder tujuan, unzip secara default berhenti dan bertanya interaktif untuk setiap konflik, perilaku yang sama merepotkannya untuk script otomatis seperti prompt overwrite ffmpeg di 14.1.2. Opsi -o menimpa semua konflik tanpa bertanya, sedangkan -n melewati semua file yang sudah ada tanpa bertanya, dan salah satunya wajib eksplisit dipilih di dalam script.
unzip -n dokumen-penting.zip -d ~/Dokumen-Extract/14.2.3 Ekstraksi Arsip tar
Bab 13.2.3 sudah membahas sisi pembuatan arsip tar lewat opsi -czf. Mengekstraknya kembali memakai opsi -x (extract) sebagai pengganti -c, sisanya tetap sama.
tar -xzf dokumen-20260830-1200.tar.gz -C ~/Dokumen-Extract/Opsi -C di sini punya fungsi sama seperti saat membuat arsip di Bab 13.2.3: mengarahkan tar berpindah direktori kerja lebih dulu, kali ini supaya hasil ekstraksi ditaruh di folder tujuan yang diinginkan, bukan mengekstrak begitu saja ke direktori kerja saat ini. Kebiasaan verifikasi sebelum ekstraksi sungguhan tetap sama seperti dibahas di Bab 13.2.4, memakai -t untuk mengintip daftar isi arsip lebih dulu.
tar -tzf dokumen-20260830-1200.tar.gz14.2.4 Memilih Format Arsip yang Tepat
Ketiga tool di atas tidak saling menggantikan, masing-masing punya kondisi yang paling cocok dipakai, dirangkum di tabel berikut.
| Tool | Paling cocok untuk | Kompatibilitas lintas OS |
|---|---|---|
gzip | Kompresi satu file tunggal (log, dump database, dll.) | Perlu tool tambahan di Windows |
tar + gzip | Snapshot folder di lingkungan Linux/macOS, backup server | Perlu tool tambahan di Windows |
zip | Arsip yang akan dibagikan ke pengguna non-Linux | Native didukung Windows & macOS |
Di lapangan, kombinasi paling umum untuk User desktop adalah tar.gz untuk backup pribadi yang tetap di lingkungan Linux/macOS sendiri (lanjutan 13.2), dan zip begitu arsip yang sama perlu dikirim ke rekan kerja yang memakai Windows tanpa tool tambahan.
14.3 Studi Kasus: Downloader dan Organizer Media
Studi kasus ini menggabungkan seluruh teknik bab ini menjadi satu script organizer untuk folder berisi hasil unduhan/pindahan media, misalnya folder Downloads browser atau folder hasil salin dari kartu SD kamera. Perlu ditegaskan lebih dulu, script ini tidak melakukan pengunduhan lewat jaringan; kebutuhan itu baru masuk akal setelah curl/wget dibahas di Bab 22.1. Fokus di sini murni pada media yang sudah ada secara lokal di disk.
14.3.1 Rancangan Script Organizer
Script yang akan dibuat menjalankan lima langkah berurutan: mengelompokkan file berdasarkan jenisnya memakai associative array seperti pola Bab 13.3.2, mengonversi gambar dan video ke format standar lewat teknik 14.1, menambahkan awalan tanggal seperti 14.1.4, memindahkan file sumber yang sudah dikonversi ke folder Asli supaya tidak diproses ulang di eksekusi berikutnya, lalu mengarsipkan hasilnya lewat zip dari 14.2.2. Argumen folder sumber diterima lewat getopts, teknik parsing opsi dari Bab 12.2, supaya script bisa dipakai untuk folder mana pun tanpa mengedit isi script.
14.3.2 Implementasi Script Lengkap
#!/bin/bash
set -uo pipefail
usage() {
echo "Penggunaan: $0 -s FOLDER_SUMBER [-a]" >&2
echo " -s FOLDER_SUMBER folder berisi media yang akan dirapikan" >&2
echo " -a arsipkan hasilnya jadi satu file zip" >&2
exit 1
}
arsipkan=0
while getopts ":s:ah" opt; do
case "$opt" in
s) sumber="$OPTARG" ;;
a) arsipkan=1 ;;
h) usage ;;
*) usage ;;
esac
done
[[ -n "${sumber:-}" && -d "$sumber" ]] || usage
if command -v magick &> /dev/null; then
IM_MOGRIFY="magick mogrify"
else
IM_MOGRIFY="mogrify"
fi
tanggal="$(date +%Y%m%d)"
mkdir -p "$sumber/Foto" "$sumber/Video" "$sumber/Asli"
declare -A kategori=(
["jpg"]="Foto" ["jpeg"]="Foto" ["png"]="Foto" ["heic"]="Foto"
["mov"]="Video" ["mp4"]="Video" ["mkv"]="Video"
)
for file in "$sumber"/*; do
[[ -f "$file" ]] || continue
nama_file=$(basename "$file")
ekstensi="${nama_file##*.}"
ekstensi="${ekstensi,,}"
tujuan="${kategori[$ekstensi]:-}"
[[ -n "$tujuan" ]] || continue
if [[ "$tujuan" == "Foto" && "$ekstensi" != "jpg" ]]; then
$IM_MOGRIFY -path "$sumber/Foto" -format jpg "$file" || continue
mv -n -- "$sumber/Foto/${nama_file%.*}.jpg" \
"$sumber/Foto/${tanggal}_${nama_file%.*}.jpg"
mv -n -- "$file" "$sumber/Asli/$nama_file"
elif [[ "$tujuan" == "Video" && "$ekstensi" != "mp4" ]]; then
ffmpeg -n -i "$file" -c:v libx264 -crf 23 -c:a aac \
"$sumber/Video/${tanggal}_${nama_file%.*}.mp4" || continue
mv -n -- "$file" "$sumber/Asli/$nama_file"
else
mv -n -- "$file" "$sumber/$tujuan/${tanggal}_${nama_file}"
fi
done
if [[ "$arsipkan" -eq 1 ]]; then
zip -r "$sumber/media-${tanggal}.zip" "$sumber/Foto" "$sumber/Video"
fi
echo "Selesai. Hasil ada di $sumber/Foto dan $sumber/Video."set -uo pipefail di baris kedua membuat script langsung berhenti kalau ada variabel yang belum di-set terpanggil, sesuai pembahasan mode debug yang akan diperdalam lagi di Bab 25.1. Optstring ":s:ah" pada getopts, mengikuti sintaks dasar dari Bab 12.2.1, mendaftarkan tiga opsi: s dan a diawali tanda titik dua langsung setelah s untuk menandai bahwa -s wajib disertai argumen (ditampung di OPTARG), sedangkan a dan h murni flag tanpa argumen. Tanda titik dua paling depan sebelum s mengaktifkan mode silent error dari Bab 12.2.3, membuat opsi tidak dikenal atau argumen yang hilang masuk ke cabang *) di dalam case alih-alih menampilkan pesan error bawaan getopts yang kurang informatif. Baris [[ -n "${sumber:-}" && -d "$sumber" ]] || usage memvalidasi folder sumber benar-benar diberikan lewat opsi -s dan memang ada di disk sebelum lanjut, memakai nilai default kosong dari Bab 6.4.4 supaya tidak error kalau -s tidak disertakan sama sekali.
Variabel $IM_MOGRIFY di dalam loop sengaja dipanggil tanpa tanda kutip ganda, satu-satunya pengecualian dari kebiasaan "selalu kutip variabel" yang ditekankan sejak Bab 3.4 dan ditegaskan lagi lewat jebakan unquoted variable di Bab 6.2.4. Nilainya berupa dua kata terpisah, magick mogrify (lihat 14.1.1), dan pemanggilan tanpa kutip inilah yang membuat Bash melakukan word splitting dari Bab 7.1.5, memecahnya jadi perintah magick dengan argumen pertama mogrify. Kalau variabel ini dikutip jadi "$IM_MOGRIFY", Bash justru mencarinya sebagai satu nama perintah tunggal berisi spasi, yang jelas tidak ada, dan pemanggilannya gagal. Percabangan tiga arah di dalam loop memilih jalur konversi yang tepat: gambar non-jpg dikonversi lewat $IM_MOGRIFY, video non-mp4 dikonversi lewat ffmpeg, sisanya (yang sudah berformat standar) cukup dipindah dan diberi awalan tanggal. Pola ${nama_file%.*} di dua cabang pertama sama seperti contoh laporan.data.tar.gz di Bab 13.1.2: memotong ekstensi terakhir saja, sehingga hasil konversi bisa ditempeli ekstensi baru (.jpg atau .mp4) tanpa membawa ekstensi asalnya.
|| continue setelah pemanggilan $IM_MOGRIFY maupun ffmpeg menerapkan saran troubleshooting di 14.1.5: kalau konversi gagal (misalnya format .heic tidak didukung instalasi ImageMagick yang dipakai), exit status-nya bukan nol, loop langsung lompat ke file berikutnya lewat continue dari Bab 7.3.2 tanpa memindahkan file yang gagal dikonversi ke folder Asli. File yang gagal itu pun tetap tertinggal apa adanya di folder sumber, gampang ditemukan lagi untuk ditangani manual, bukan hilang atau diam-diam tercatat sebagai "sudah selesai". Baris mv -n -- "$file" "$sumber/Asli/$nama_file" setelah konversi berhasil memindahkan file sumber aslinya ke folder Asli, bukan menghapusnya, dua alasan sekaligus: menjaga salinan asli seandainya hasil konversi ternyata bermasalah, dan mencegah file yang sama diproses ulang kalau script ini dijalankan lagi di folder yang sama.
14.3.3 Verifikasi dan Pengembangan Lanjutan
Beri izin eksekusi dan jalankan seperti kebiasaan di Bab 1.4.3, lalu verifikasi hasilnya lewat ls.
chmod +x organizer-media.sh
./organizer-media.sh -s ~/Downloads -a
ls ~/Downloads/Foto ~/Downloads/Video ~/Downloads/Asli
unzip -l ~/Downloads/media-"$(date +%Y%m%d)".zipUji dulu di folder salinan berisi beberapa file sampel, bukan langsung ke folder Downloads asli, sesuai kebiasaan dry-run yang sudah ditekankan berulang kali sejak Bab 13.1.4. Kalau salinan uji coba tadi berisi file .heic, cek dulu dukungannya lewat perintah di 14.1.5 sebelum menjalankan ke koleksi sungguhan, supaya file semacam ini tidak menumpuk gagal diam-diam di folder sumber. Perhatikan juga proses konversi video lewat ffmpeg bisa memakan waktu cukup lama untuk file berukuran besar atau berjumlah banyak, jadi wajar kalau script terlihat "diam" selama proses encoding berjalan; itu bukan tanda script macet, cukup pantau lewat top/htop (dibahas lebih dalam di Bab 17.2) kalau ingin memastikan prosesnya masih berjalan aktif.
Pengembangan lanjutan yang wajar ditambahkan adalah rotasi otomatis, menghapus file di folder Foto/Video yang usianya sudah lebih dari beberapa bulan, memakai pola find -mtime yang sama seperti dibahas di Bab 13.2.4. Kalau script ini nantinya juga ingin dijalankan otomatis setiap hari tanpa perlu diingat-ingat manual, teknik penjadwalannya dibahas di Bab 15.1. Tiga kebutuhan multimedia di bab ini, konversi batch, kompresi/ekstraksi arsip, dan organizer otomatis, melengkapi kebutuhan otomatisasi harian yang dimulai di Bab 13. Bab 15 melanjutkan ke sisi produktivitas lain: reminder, integrasi aplikasi desktop, dan dotfiles untuk setup environment baru.

