Sistem yöneticiliğinde işlerin gerçekten karmaşıklaştığı an, tek bir dosyayla değil yüzlerce, binlerce dosyayla aynı anda ilgilenmen gerektiği andır. Üretim sunucusunda log dosyalarını temizlemek, yetki sorunlarını düzeltmek ya da toplu yeniden adlandırma yapmak… Bunların hepsinde ortak bir ihtiyaç var: özyinelemeli işlemler. Dizin ağaçlarında tek komutla derinlemesine ilerleyip her dosyaya ya da dizine aynı işlemi uygulayabilmek, sysadmin’in en güçlü silahlarından biridir.
Özyinelemeli İşlem Nedir?
Özyinelemeli (recursive) işlem, bir komutun yalnızca belirtilen dizinde değil, o dizinin altındaki tüm alt dizinlerde ve dosyalarda da çalışmasını sağlar. Linux’ta bu genellikle -R veya -r parametresiyle ya da find komutunun -exec seçeneğiyle gerçekleştirilir.
Basit bir örnekle başlayalım. Diyelim ki /var/www/html altındaki tüm dosyaları listelemek istiyorsun:
ls -lR /var/www/html
Bu komut, dizin ağacını yukarıdan aşağıya doğru gezer ve her seviyedeki içeriği gösterir. Kulağa basit gelebilir ama bu mantığı chmod, chown, find, grep gibi komutlarla birleştirdiğinde inanılmaz derecede güçlü hale gelir.
find Komutu: Özyinelemeli İşlemlerin Kalbi
Linux’ta özyinelemeli işlemlerin merkezinde find komutu durur. find olmadan ciddi bir sistem yöneticisi olamazsın. Temel sözdizimi şu şekildedir:
find [başlangıç_dizini] [koşullar] [eylem]
find komutu varsayılan olarak özyinelemeli çalışır; yani belirttiğin dizinden başlayarak tüm alt dizinleri gezer. Bunu kısıtlamak için -maxdepth parametresini kullanabilirsin.
Gerçek dünya senaryosu: Bir web sunucusunda .log uzantılı tüm dosyaları bulmak istiyorsun.
find /var/log -name "*.log" -type f
-name: Dosya adı kalıbını belirtir (büyük/küçük harf duyarlı) -type f: Yalnızca dosyaları getirir (dizinleri hariç tutar) -type d: Yalnızca dizinleri getirir -maxdepth 2: En fazla 2 seviye derinlikte arar -mindepth 1: En az 1 seviye derinlikten itibaren arar
Büyük/küçük harf fark etmeksizin aramak için -iname kullanabilirsin:
find /home -iname "*.txt" -type f
chmod ile Toplu Yetki Düzeltme
Yetki sorunları sysadmin’lerin en sık karşılaştığı problemlerden biridir. Özellikle FTP veya SFTP üzerinden yüklenen dosyalarda izinler sıklıkla bozulur. Bir web sitesinin dosya yapısını düşün: dizinlerin 755, dosyaların ise 644 olması gerekiyor. Bunu elle tek tek düzeltmek imkansız.
İşte burada özyinelemeli chmod devreye girer:
# Tüm dizinlere 755 ver
find /var/www/html -type d -exec chmod 755 {} ;
# Tüm dosyalara 644 ver
find /var/www/html -type f -exec chmod 644 {} ;
-exec parametresi, bulunan her öğe için belirtilen komutu çalıştırır. {} bulunan dosyanın yerini tutar, ; ise komutun sonunu belirtir.
Alternatif olarak + kullanabilirsin; bu yöntem daha hızlıdır çünkü dosyaları toplu olarak işler:
find /var/www/html -type f -exec chmod 644 {} +
Önemli bir senaryo: PHP uygulamalarında özellikle storage ve cache dizinlerine yazma izni gerekir. Laravel projelerinde sık karşılaşılan bu durumu şöyle çözebilirsin:
find /var/www/myapp/storage -type d -exec chmod 775 {} ;
find /var/www/myapp/storage -type f -exec chmod 664 {} ;
chown -R www-data:www-data /var/www/myapp/storage
chown ile Toplu Sahiplik Değiştirme
Sunuculara yeni bir web uygulaması deploy ettiğinde, dosyaların sahibini web sunucusu kullanıcısına (www-data, nginx, apache gibi) ataman gerekir. -R parametresi burada işi kolaylaştırır:
chown -R www-data:www-data /var/www/html
-R: Dizini ve içindeki tüm öğeleri özyinelemeli olarak işler
Belirli uzantıdaki dosyaların sahipliğini değiştirmek için find ile birleştirebilirsin:
find /var/www/html -name "*.php" -type f -exec chown www-data:www-data {} ;
Gerçek dünya senaryosu: Bir müşterinin sitesini bir sunucudan diğerine taşıdın. Eski sunucuda kullanıcı ID’si 1001 olan webuser vardı ama yeni sunucuda bu kullanıcı yok. Tüm dosyalar sayısal UID gösteriyor:
# Önce eski UID'ye ait dosyaları bul
find /var/www -uid 1001 -type f
# Sonra yeni kullanıcıya ata
find /var/www -uid 1001 -exec chown newwebuser:newwebuser {} ;
grep ile Dizin Ağacında Toplu Arama
Yüzlerce config dosyası arasında belirli bir IP adresini ya da parametreyi bulmak gerektiğinde -r (recursive) ve -l parametreleri hayat kurtarır:
grep -r "database_host" /etc/myapp/
-r: Tüm alt dizinlerde özyinelemeli arama yapar -l: Sadece eşleşen dosyaların adını gösterir (içeriği değil) -i: Büyük/küçük harf duyarsız arama -n: Eşleşmenin kaçıncı satırda olduğunu gösterir -H: Dosya adını da gösterir
Daha pratik bir örnek. Bir güvenlik açığı duyurusu çıktı ve tüm PHP dosyalarında eval(base64_decode kullanımını aramak istiyorsun:
grep -r --include="*.php" -l "eval(base64_decode" /var/www/
--include parametresi aramanın yalnızca belirtilen dosya uzantılarında yapılmasını sağlar. Bu çok önemli bir optimizasyon; yoksa binary dosyalarda da arama yaparak hem zaman kaybedersin hem de anlamsız çıktılar alırsın.
Birden fazla uzantıyı birlikte arayabilirsin:
grep -r --include="*.conf" --include="*.cfg" "ServerName" /etc/
find + xargs Kombinasyonu: Performansı Artır
-exec parametresi her eşleşme için ayrı bir process başlatır. Yüz binlerce dosyayla çalışırken bu büyük bir performans sorunu yaratır. xargs ise bulunan tüm sonuçları toplu olarak işleyerek çok daha verimli çalışır:
# -exec yöntemi (yavaş)
find /tmp -name "*.tmp" -type f -exec rm {} ;
# xargs yöntemi (hızlı)
find /tmp -name "*.tmp" -type f | xargs rm
Ancak dosya adlarında boşluk varsa xargs sorun çıkarır. Bunu çözmek için find‘ın -print0 ve xargs‘ın -0 parametresini kullan:
find /tmp -name "*.tmp" -type f -print0 | xargs -0 rm -f
Gerçek dünya senaryosu: Bir uygulama dizininde 30 günden eski tüm geçici dosyaları silmek istiyorsun:
find /var/app/temp -type f -mtime +30 -print0 | xargs -0 rm -f
-mtime +30: 30 günden daha eski dosyalar -mtime -7: Son 7 günde değiştirilen dosyalar -mtime 0: Bugün değiştirilen dosyalar
Zamana Dayalı Özyinelemeli İşlemler
Log yönetimi her sysadmin’in günlük rutininin parçasıdır. Eski logları arşivlemek ya da silmek için zaman tabanlı filtreleme şarttır:
# 7 günden eski log dosyalarını bul ve sil
find /var/log/nginx -name "*.log" -type f -mtime +7 -delete
# Son 24 saatte oluşturulan dosyaları listele
find /var/www/uploads -type f -newer /var/www/uploads/.timestamp
-delete parametresi -exec rm {} ; yerine kullanılabilir ve çok daha hızlıdır. Ancak dikkat: -delete kullanmadan önce mutlaka önce -print veya sadece find komutuyla sonuçları gör, doğru dosyaları hedeflediğinden emin ol.
Boyuta göre filtreleme de oldukça kullanışlıdır:
# 100MB'den büyük dosyaları bul
find /var -type f -size +100M
# 0 byte olan boş dosyaları bul ve sil
find /tmp -type f -empty -delete
-size +100M: 100 megabyte’tan büyük -size -1k: 1 kilobyte’tan küçük -size 0: Boş dosyalar -empty: Boş dosyalar veya dizinler
Toplu Yeniden Adlandırma
Bazen yüzlerce dosyayı belirli bir kurala göre yeniden adlandırman gerekir. rename komutu bu iş için biçilmiş kaftandır. Debian/Ubuntu’da rename Perl tabanlıdır ve regex destekler:
# Tüm .htm dosyalarını .html yap
find /var/www -name "*.htm" -type f | xargs rename 's/.htm$/.html/'
# Dosya adlarındaki boşlukları alt çizgiyle değiştir
find /home/user/documents -name "* *" -type f | rename 's/ /_/g'
# Tüm dosyaları küçük harfe çevir
find /var/www/uploads -type f | rename 's/(.+)/lc($1)/e'
CentOS/RHEL sistemlerde rename komutu farklı çalışır, basit bir string değiştirme yapar:
# Tüm .conf.bak dosyalarını .conf yap
find /etc/nginx/sites-available -name "*.conf.bak" | xargs -I{} bash -c 'mv "$1" "${1%.bak}"' -- {}
Bash Döngüleriyle Özyinelemeli İşlemler
Bazen find ve xargs kombinasyonu yeterli olmaz; her dosya için karmaşık işlemler yapmak gerekebilir. İşte burada bash döngüleri ve globstar devreye girer:
# globstar aktif et
shopt -s globstar
# Tüm PHP dosyalarını işle
for file in /var/www/**/*.php; do
# Her dosyada belirli bir string'i değiştir
sed -i 's/old_function/new_function/g' "$file"
echo "İşlendi: $file"
done
Gerçek dünya senaryosu: Bir projeyi yeni bir veritabanı sunucusuna taşıdın ve onlarca config dosyasında eski IP adresini güncellemen gerekiyor:
# Önce neyin değişeceğini gör
grep -r "192.168.1.100" /etc/myapp/ --include="*.conf"
# Sonra güvenli şekilde değiştir
find /etc/myapp -name "*.conf" -type f -exec sed -i 's/192.168.1.100/10.0.0.50/g' {} ;
# Değişiklikleri doğrula
grep -r "10.0.0.50" /etc/myapp/ --include="*.conf"
sed -i komutu dosyayı yerinde (in-place) düzenler. Dikkat: Büyük değişiklikler yapmadan önce yedek almayı unutma. sed -i.bak kullanarak orijinal dosyanın .bak uzantılı yedeğini otomatik oluşturabilirsin:
find /etc/myapp -name "*.conf" -type f -exec sed -i.bak 's/192.168.1.100/10.0.0.50/g' {} ;
Özyinelemeli Kopyalama ve Senkronizasyon
cp komutunun -r parametresi dizin ağaçlarını kopyalar:
cp -r /var/www/html /backup/html_$(date +%Y%m%d)
Ancak büyük dizin yapılarını kopyalamak ya da iki sunucu arasında senkronizasyon yapmak için rsync çok daha güçlüdür:
# Yerel yedekleme
rsync -avz /var/www/html/ /backup/html/
# Uzak sunucuya senkronize et
rsync -avz --delete /var/www/html/ user@backup-server:/backup/html/
# Belirli dosyaları hariç tut
rsync -avz --exclude="*.log" --exclude="cache/" /var/www/html/ /backup/html/
-a: Archive modu (özyinelemeli, izinleri ve sembolik linkleri korur) -v: Verbose (ayrıntılı çıktı) -z: Sıkıştırarak transfer eder –delete: Hedefte olup kaynakta olmayan dosyaları siler
Özyinelemeli İşlemlerde Güvenlik ve Dikkat Edilmesi Gerekenler
Özyinelemeli işlemler güçlüdür; bu yüzden dikkatli kullanılmalıdır. Birkaç kritik kural:
Önce test et: find komutunu önce eylemsiz çalıştır, hangi dosyaları etkileyeceğini gör. -delete veya -exec rm eklemeden önce çıktıyı incele.
rm -rf tuzağına düşme: rm -rf / ya da yanlış bir path ile çalıştırılan bir komut sistemi bitirebilir. find ile silme yaparken şöyle bir güvenlik önlemi alabilirsin:
# Önce listele
find /tmp/myapp -name "*.tmp" -type f -mtime +7
# Sonuçtan memnunsan sil
find /tmp/myapp -name "*.tmp" -type f -mtime +7 -delete
xargs ile boş sonuçlara dikkat: find hiçbir şey bulamazsa xargs rm tehlikeli olabilir. -r veya --no-run-if-empty parametresini kullan:
find /tmp -name "*.tmp" -print0 | xargs -0 -r rm -f
Sembolik linkleri dikkatli izle: find varsayılan olarak sembolik linkleri takip etmez. Eğer takip etmesini istersen -L parametresini kullan ama bu sonsuz döngülere yol açabilir, dikkatli ol:
find -L /var/www -name "*.php" -type f
Sistem dizinlerini hariç tut: Tüm diskte arama yaparken /proc, /sys, /dev gibi sanal dosya sistemlerini hariç tutman gerekir:
find / -name "*.log" -not -path "/proc/*" -not -path "/sys/*" -type f
Pratik Bir Senaryo: Sunucu Sertleştirme Scripti
Tüm öğrendiklerini bir araya getiren gerçekçi bir örnek. Yeni kurulmuş bir web sunucusunu hızlıca güvenli hale getirmek için:
#!/bin/bash
WEB_ROOT="/var/www/html"
WEB_USER="www-data"
echo "Dizin izinleri düzenleniyor..."
find "$WEB_ROOT" -type d -exec chmod 755 {} ;
echo "Dosya izinleri düzenleniyor..."
find "$WEB_ROOT" -type f -exec chmod 644 {} ;
echo "PHP dosyaları kontrol ediliyor..."
find "$WEB_ROOT" -name "*.php" -exec chmod 644 {} ;
echo "Yazılabilir dizinler ayarlanıyor..."
find "$WEB_ROOT/storage" -type d -exec chmod 775 {} ;
find "$WEB_ROOT/storage" -type f -exec chmod 664 {} ;
echo "Sahiplik ayarlanıyor..."
chown -R "$WEB_USER:$WEB_USER" "$WEB_ROOT"
echo "Şüpheli dosyalar aranıyor..."
grep -r --include="*.php" -l "eval(base64_decode" "$WEB_ROOT" && echo "UYARI: Şüpheli dosyalar bulundu!"
echo "30 günden eski log dosyaları temizleniyor..."
find /var/log/nginx -name "*.log.gz" -mtime +30 -delete
echo "Tamamlandı."
Bu script tek bir çalıştırmayla onlarca ayrı işlemi gerçekleştiriyor. İşte özyinelemeli işlemlerin gücü tam olarak bu.
Sonuç
Özyinelemeli işlemler, Linux sistem yönetiminin olmazsa olmaz parçasıdır. find komutunu -exec, xargs, grep, sed, chmod, chown gibi araçlarla birleştirdiğinde dizin ağaçlarında ne kadar güçlü işlemler yapabileceğini gördük.
En önemli nokta şu: bu komutlar geri alınamaz sonuçlar doğurabilir. Özellikle silme ve toplu değiştirme işlemlerinde önce sonuçları görsel olarak incele, kritik dizinlerde test et ve mümkünse yedek al. sed -i.bak, find ... -print gibi güvenli adımlar seni büyük felaketlerden korur.
Bir kez alışkanlık haline getirdiğinde bu komutları, saatler sürecek elle yapılan işlemleri dakikalara indireceksin. Ve bu, iyi bir sysadmin’in temel özelliklerinden biridir: tekrar eden işleri otomatize etmek, zamanını daha önemli şeylere ayırmak.