mmv Komutu ile Desen Tabanlı Toplu Dosya Taşıma ve Yeniden Adlandırma

Yıllarca mv komutuyla tek tek dosya taşıdıysanız, ya da for döngüleriyle onlarca satır bash yazdıysanız, bu yazıyı okuduktan sonra kendinize biraz kızacaksınız. mmv tam olarak o “keşke bunun bir kısayolu olsaydı” hissini karşılayan bir araç. Kurulumu iki saniye, öğrenmesi on dakika, ama tasarrufu saatler.

mmv Nedir ve Neden Kullanmalısınız

mmv (multiple move), tek bir komutla joker karakter kalıpları kullanarak onlarca, hatta yüzlerce dosyayı aynı anda taşımanıza, yeniden adlandırmanıza, kopyalamanıza veya bağlamanıza olanak tanır. Standart mv komutundan temel farkı şu: hedef kalıpta, kaynak kalıptan yakalanan grupları geri çağırabilirsiniz. Bu özellik, dosya adlarının bir bölümünü koruyarak kalan kısmını değiştirmenizi son derece pratik hale getirir.

Mesela yüzlerce .jpeg dosyasını .jpg yapmak istiyorsunuz. Normalde bunu bir bash döngüsüyle yapardınız:

for f in *.jpeg; do mv "$f" "${f%.jpeg}.jpg"; done

mmv ile bu sadece şu kadar:

mmv "*.jpeg" "#1.jpg"

Sadelik açısından kıyaslamak bile saçma geliyor.

Kurulum

Çoğu dağıtımda paket depolarında hazır bulunur:

# Debian/Ubuntu
sudo apt install mmv

# Fedora/RHEL/CentOS
sudo dnf install mmv

# Arch Linux
sudo pacman -S mmv

# macOS (Homebrew ile)
brew install mmv

Kurulumdan sonra man sayfasına bir göz atın, oldukça sade ve okunabilir:

man mmv

Temel Sözdizimi ve Parametreler

mmvnin temel kullanımı şu yapıdadır:

mmv [seçenekler] "kaynak_kalıbı" "hedef_kalıbı"

Buradaki kritik nokta şu: kaynak kalıbındaki her * (ya da ?) joker karakteri, hedef tarafında #1, #2, #3 şeklinde numaralandırılarak geri çağrılır. Birden fazla joker varsa sırayla #1, #2 diye devam eder.

Temel parametreler şunlardır:

  • -n: Dry-run (deneme) modu. Hiçbir şeyi gerçekten yapmaz, sadece ne yapacağını gösterir. Üretim ortamlarında her zaman önce bunu çalıştırın.
  • -v: Verbose mod. Her işlemi ekrana yazar.
  • -f: Force. Hedef dosya zaten varsa üzerine yazar.
  • -i: Interactive. Üzerine yazmadan önce sorar.
  • -d: Directory oluşturma. Hedef dizin yoksa otomatik oluşturur.
  • -r: Rename zincirlerini çözer. Aynı ada sahip birden fazla dosya varsa çakışmaları halleder.
  • -e: Execute. Birden fazla komutu birleştirerek çalıştırır (genelde komut satırı argümanlarıyla).
  • -m: Move (varsayılan). Dosyaları taşır.
  • -c: Copy. Taşımak yerine kopyalar.
  • -l: Hard link oluşturur.
  • -s: Symbolic link oluşturur.

Dry-Run ile Güvenli Çalışma

Üretim sisteminde ya da kritik dosyalar üzerinde çalışırken -n parametresi hayat kurtarır. Yaptığınız şeyin gerçekten istediğiniz şey olup olmadığını doğrulamadan hiçbir mmv komutunu çalıştırmamanızı öneririm.

# Önce ne yapacağını gör
mmv -n "report_*.txt" "rapor_#1.txt"

# Çıktı istediğin gibiyse, şimdi gerçekten çalıştır
mmv "report_*.txt" "rapor_#1.txt"

Dry-run çıktısı size report_2023.txt -> rapor_2023.txt şeklinde her satırda bir dönüşüm gösterir. Bu çıktıyı gözden geçirmeden komutu gerçekten çalıştırmak, özellikle joker karakterlerin beklediğinizden farklı dosyaları eşleştirdiği durumlarda ciddi baş ağrısı yaratabilir.

Gerçek Dünya Senaryoları

Senaryo 1: Uzantı Değiştirme (Toplu)

Bir web projesinde çalışırken fotoğrafçıdan gelen tüm görseller .JPG uzantılıyla geldi ama nginx konfigürasyonunuz küçük harf .jpg bekliyor. Yüzlerce dosya var.

# Büyük harf uzantıyı küçüğe çevir
mmv "*.JPG" "#1.jpg"

# Aynı mantıkla PNG için
mmv "*.PNG" "#1.png"

Burada #1 kaynak kalıptaki ilk *e karşılık gelir, yani dosya adının uzantısız kısmı. Uzantı ayrıca belirtildiği için sadece o değişir.

Senaryo 2: Tarih Bazlı Log Dosyalarını Yeniden Düzenleme

Uygulama logları app-2024-01-15.log formatında geliyor, ama arşiv sisteminiz 20240115-app.log formatı bekliyor. Elle yapmayı hayal bile etmiyorum.

# Önce dry-run
mmv -n "app-????-??-??.log" "#4#5#6#7#8#9-app.log"

Burada ? tek karakter eşler. Dört ? yıl için, iki ? ay için, iki ? gün için. Sonra bunlar #1 ile #8 arasında sıralanır. Aşağıdaki yaklaşım biraz daha okunabilir olabilir:

# Yıl-ay-gün ile çalışan bir örnek
mmv -n "app-*-*-*.log" "#2#3#4-app.log"

Burada --* ile üç grup yakalanıyor: #1 yıl, #2 ay, #3 gün.

Senaryo 3: Proje Klasörleri Arasında Toplu Taşıma

Bir yazılım ekibinde modül bazlı yeniden yapılanma oldu. lib/ altındaki tüm *.conf dosyalarının config/ dizinine taşınması gerekiyor.

# Dizin yoksa -d ile birlikte oluştur
mmv -d "lib/*.conf" "config/#1.conf"

-d parametresi config/ dizini henüz yoksa onu da oluşturur. Bu özellik olmadan ayrıca mkdir -p config yapmanız gerekirdi.

Senaryo 4: Numara Dolgulama (Zero Padding)

Medya dosyalarını sıralı şekilde işleyen bir pipeline’da dosya adlarındaki sayıların sıfır dolgulu (zero-padded) olması gerekiyor. track1.mp3, track2.mp3 gibi dosyaların track01.mp3, track02.mp3 olmasını istiyorsunuz.

# Tek haneli sayıları iki haneye tamamla
mmv "track?.mp3" "track0#1.mp3"

Buradaki ? tek karakter yakalar, yani sadece tek basamaklı sayılar (1-9) için çalışır. İki basamaklıları bozmaması için kalıp yeterince spesifik.

Senaryo 5: Alt Dizinlerdeki Dosyaları Düzleme

Çeşitli alt klasörlere dağılmış backup dosyalarını tek bir arşiv klasöründe toplamak gerekiyor. Örneğin 2024/01/backup.sql, 2024/02/backup.sql gibi yapıyı archives/backup_2024_01.sql formatına çevirmek istiyorsunuz.

mmv -n "????/??/backup.sql" "archives/backup_#1_#2.sql"

mmv alt dizin yapılarında da joker karakterlerle çalışabilir, ancak bu konuda dikkatli olmak gerekir, özellikle de dizin sınırlarını aşan eşleştirmelerde. Bazı sürümlerde **/ path separator desteği sınırlı olabilir, bunu test ederek doğrulamak önemli.

Senaryo 6: Kopyalama ile Yedek Oluşturma

Bir konfigürasyon değişikliği öncesinde tüm .conf dosyalarının .conf.bak kopyasını almak istiyorsunuz:

# -c ile kopyala (orijinallere dokunma)
mmv -c "*.conf" "#1.conf.bak"

Şimdi hem orijinaller hem de .bak uzantılı kopyaları yan yana duruyor. Rollback gerekirse:

mmv "*.conf.bak" "#1.conf"

Bu kadar. İki komutla backup al, iki komutla geri dön.

Senaryo 7: Sembolik Link Yaratma

Nginx site konfigürasyonlarında sites-available ile sites-enabled arasında sembolik link oluşturma işini elle yapmaktan sıkıldınız diyelim:

# sites-available altındaki tüm .conf dosyaları için sites-enabled'da symlink oluştur
mmv -s "/etc/nginx/sites-available/*.conf" "/etc/nginx/sites-enabled/#1.conf"

Tabii bu örnekte dikkatli olun, zaten varolan linkler için -f parametresi gerekebilir.

İki Joker ile Çalışmak

Birden fazla joker kullandığınızda gruplar sırayla numaralanır. Bunu bir kere içselleştirince çok güçlü dönüşümler yazabiliyorsunuz.

# "client_adi-proje_kodu_2024.pdf" formatını
# "2024/adi/proje_kodu.pdf" formatına çevir
mmv "*-*_2024.pdf" "2024/#1/#2.pdf"

Burada ilk müşteri adı (#1), ikinci proje kodu (#2). Yıl sabit olduğu için kalıpta direkt yazıldı, ama hedefte dizin olarak kullanıldı.

Birden fazla joker kullanırken dry-run’ın önemi daha da artıyor çünkü hangi grubun neye karşılık geldiğini gözle takip etmek zorlaşıyor.

Çakışma Yönetimi

mmv çakışmaları otomatik olarak yönetir; bu onu mv‘den önemli ölçüde güçlü kılan özelliklerden biri. Örneğin bir döngülü yeniden adlandırma yapıyorsunuz: a.txt -> b.txt ve aynı anda b.txt -> a.txt. Standart mv bunu sıralamaya bağlı olarak ya bozar ya kaybeder. mmv ise -r parametresiyle bu zincirleri çözüp doğru sırada işler:

mmv -r "a.txt" "b.txt"
# ve ayrı bir komutla
mmv -r "b.txt" "a.txt"

Ya da daha gerçekçi bir örnek: bir grup dosyayı sırayla bir öne kaydırmak. file1, file2, file3 varken file2‘yi file1 yapmak istiyorsunuz. -r olmadan bu işlem mevcut file1‘in üzerine yazar ya da hata verir.

Dikkat Edilmesi Gereken Noktalar

Birkaç yılda bir bu komutla ciddi bir sorun yaşadım ya da yaşanmasını önledim. Öğrendiklerimi aktarayım:

Tırnak kullanımı zorunlu. Kalıpları mutlaka çift tırnak içine alın. Aksi hâlde bash önce kendi glob genişlemesini yapar ve mmv yanlış argümanlar alır. Bu en sık yapılan hata.

Boşluk içeren dosya adları. * joker karakteri boşluk içeren dosya adlarını da yakalar. Hedef kısımda #1 ile geri çağırdığınızda boşluklar da taşınır. Genel olarak sorun çıkarmaz ama oluşturulan dosya adında beklenmedik boşluk içeren bir yapı varsa dikkatli olun.

Büyük/küçük harf duyarlılığı. Linux dosya sistemi case-sensitive olduğu için .JPG ile .jpg farklı dosyaları yakalar. macOS’un varsayılan HFS+ dosya sistemi ise case-insensitive’dir, bu da bazen beklenmedik sonuçlar doğurabilir.

Hedef dizinin varlığı. -d parametresi olmadan, hedef dizin yoksa komut hata verir. Bunu unutmak zaman zaman sinir bozucu olabiliyor.

Root ile çalışmak. Sistem dizinlerinde mmv kullanıyorsanız, yanlış bir kalıpla kritik dosyaları taşıma ya da üzerine yazma riski var. Her zamankinden daha dikkatli olun ve dry-run atlama.

Bash Scriptleri ile Entegrasyon

mmv cron job’larında ve otomasyon scriptlerinde gayet iyi çalışır. Örneğin her gece çalışan bir log rotasyon scripti:

#!/bin/bash

# Dünkü logları arşiv klasörüne taşı
TARIH=$(date -d "yesterday" +%Y%m%d)
mmv -v "*.log" "${TARIH}_#1.log" >> /var/log/log_rotation.log 2>&1

# Taşınan dosyaları arşiv klasörüne gönder
mmv -v "${TARIH}_*.log" "/var/log/archive/#1"

Burada -v verbose modun çıktısını log dosyasına yönlendirmek, hangi dosyaların işlendiğini takip etmek açısından önemli. Özellikle bir şeyler ters giderse geri dönüp bakabileceğiniz bir iz bırakmış olursunuz.

mmv ile rename Karşılaştırması

Perl tabanlı rename komutu da benzer işler yapabilir ve regex desteğiyle bazı durumlarda daha güçlüdür. Ama mmvnin avantajları şunlardır:

  • Sözdizimi çok daha sade, regex bilmeden kullanılabilir
  • Taşıma ve dizin değiştirme aynı anda yapılabilir
  • Kopyalama ve link oluşturma yerleşik özellik olarak geliyor
  • Zincirleme çakışmaları otomatik çözüyor

rename ise uzantı veya içerik bazlı karmaşık dönüşümlerde (s/eski/yeni/g tarzı) daha esnektir. İkisinin de yerini bilen sysadmin, doğru aracı doğru işe kullanır.

Sonuç

mmv küçük, odaklı ve işini son derece iyi yapan bir araç. Öğrenme eğrisi neredeyse yok, #1, #2 sistemini bir kez kavradıktan sonra geri kalanı otomatik geliyor. Ben bunu öğrendikten sonra for f in ...; do mv ...; done döngülerinin büyük çoğunluğunu scriptlerimden sildim.

Özellikle şu üç durumda aklınıza gelmesi gerekiyor: toplu uzantı değişikliği, dosya adı formatı dönüşümü ve dizinler arası toplu taşıma. Bu üç senaryo sysadmin hayatının oldukça büyük bir bölümünü kapsar.

Son bir not: her ne kadar mmv güvenilir bir araç olsa da, özellikle geri alınamaz işlemler (move, overwrite) için dry-run adımını atlamamak iyi bir alışkanlık. Bunu bir kere atlamak, bir kez fazla atlamaktan çok daha pahalıya mal olabilir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir