KOMUT.IO Başlangıçtan ileri seviyeye, geliştirici ve sysadmin rehberi.

comm Komutu ile Sıralı Dosyaları Karşılaştırma ve Fark Bulma

c

comm Komutu ile Sıralı Dosyaları Karşılaştırma ve Fark Bulma

Sysadmin hayatında “bu dosyada ne değişti?”, “hangi paketler eksik?”, “bu iki liste arasındaki fark nedir?” gibi sorularla sık sık karşılaşırsınız. Çoğu zaman akla ilk gelen diff komutudur. Ama comm komutunu biliyorsanız, bazı senaryolarda çok daha temiz ve kullanışlı sonuçlar elde edebilirsiniz.

Bu yazıda comm komutunu A’dan Z’ye ele alacağız. Gerçek dünya örnekleriyle, ne zaman kullanmanız gerektiğini ve diff‘ten nasıl farklılaştığını göstereceğim.

comm Nedir ve Ne Zaman Kullanılır?

comm, iki sıralı metin dosyasını satır satır karşılaştıran bir Unix aracıdır. Çıktısını üç sütun halinde verir:

  • Sütun 1: Sadece birinci dosyada olanlar
  • Sütun 2: Sadece ikinci dosyada olanlar
  • Sütun 3: Her iki dosyada da olanlar (ortak satırlar)

diff komutundan temel farkı şudur: diff değişiklik bloklarını gösterir, ekleme/silme satırlarını işaretler. comm ise setler teorisi mantığıyla çalışır. “A kümesinde olup B’de olmayan”, “B’de olup A’da olmayan”, “her ikisinde de olan” şeklinde düşünün.

Önemli bir not: Dosyalar mutlaka sıralı olmalıdır. Sıralı değilse comm yanlış sonuç üretir. Bu yüzden genellikle sort komutuyla birlikte kullanılır.

Temel Kullanım

Sözdizimi son derece basit:

comm [SECENEK] dosya1 dosya2

Üç temel seçenek vardır:

  • -1 : Birinci sütunu (sadece dosya1’de olanlar) gizle
  • -2 : İkinci sütunu (sadece dosya2’de olanlar) gizle
  • -3 : Üçüncü sütunu (ortak olanlar) gizle

Bu seçenekleri birleştirerek istediğiniz sonucu elde edersiniz.

İlk Örnek: Basit Karşılaştırma

Diyelim ki iki dosyanız var:

# dosya1.txt
cat > dosya1.txt << EOF
apache2
curl
git
mysql-server
nginx
php
EOF

# dosya2.txt
cat > dosya2.txt << EOF
apache2
docker
git
nginx
nodejs
php
redis
EOF

Şimdi comm ile karşılaştıralım:

comm dosya1.txt dosya2.txt

Çıktı şöyle görünür:

               apache2
curl
        docker
               git
mysql-server
               nginx
        nodejs
               php
        redis

Sütun 1 (girintisiz): Sadece dosya1’de olan -> curl, mysql-server Sütun 2 (bir tab girintili): Sadece dosya2’de olan -> docker, nodejs, redis Sütun 3 (iki tab girintili): Her ikisinde de olan -> apache2, git, nginx, php

Pratik Seçenek Kombinasyonları

Sadece Ortak Olanları Göster

comm -12 dosya1.txt dosya2.txt

Çıktı:

apache2
git
nginx
php

-1 ile sütun 1’i, -2 ile sütun 2’yi gizledik. Geriye sadece ortak olanlar kaldı. Bu aslında iki kümenin kesişimi.

Sadece Dosya1’de Olanları Göster

comm -23 dosya1.txt dosya2.txt

Çıktı:

curl
mysql-server

Sütun 2 ve 3’ü gizledik, sadece birinci dosyaya özgü olanlar kaldı. Bu A – B farkı.

Sadece Dosya2’de Olanları Göster

comm -13 dosya1.txt dosya2.txt

Çıktı:

docker
nodejs
redis

Bu da B – A farkı.

Gerçek Dünya Senaryoları

Senaryo 1: Kurulu Paket Listelerini Karşılaştırma

Yeni bir sunucu kuruyorsunuz ve mevcut production sunucusundaki paketlerin aynısının yüklü olmasını istiyorsunuz. Önce paket listelerini çıkarın, sonra karşılaştırın.

# Production sunucusunda
dpkg --get-selections | grep -v deinstall | awk '{print $1}' | sort > /tmp/prod_packages.txt
scp sunucu1:/tmp/prod_packages.txt /tmp/prod_packages.txt

# Yeni sunucuda
dpkg --get-selections | grep -v deinstall | awk '{print $1}' | sort > /tmp/new_packages.txt

# Prod'da olup yeni sunucuda olmayan paketler
comm -23 /tmp/prod_packages.txt /tmp/new_packages.txt

# Yeni sunucuda olup prod'da olmayan paketler (dikkat edilmesi gerekenler)
comm -13 /tmp/prod_packages.txt /tmp/new_packages.txt

Bu yöntemle kurulum eksikliklerini anında bulabilirsiniz. Onlarca paketi tek tek kontrol etmek yerine birkaç saniyede farkı görürsünüz.

Senaryo 2: Backup Dosyalarının Kontrolü

Bir dizindeki dosyaların yedeğe gittiğini doğrulamak istiyorsunuz:

# Kaynak dizindeki dosyalar
find /var/www/html -type f | sed 's|/var/www/html/||' | sort > /tmp/kaynak_dosyalar.txt

# Backup dizinindeki dosyalar
find /backup/www -type f | sed 's|/backup/www/||' | sort > /tmp/backup_dosyalar.txt

# Yedeğe gitmemiş dosyalar
echo "=== YEDEGE GITMEYEN DOSYALAR ==="
comm -23 /tmp/kaynak_dosyalar.txt /tmp/backup_dosyalar.txt

# Yedekte olup kaynakta olmayan dosyalar (silinmiş ama yedekte hala var)
echo "=== KAYNAKTA SILINMIS AMA YEDEKTE MEVCUT ==="
comm -13 /tmp/kaynak_dosyalar.txt /tmp/backup_dosyalar.txt

Bu script’i cron’a ekleyip düzenli backup kontrolü yapabilirsiniz.

Senaryo 3: Kullanıcı Hesaplarını Karşılaştırma

İki sunucu arasındaki kullanıcı farklarını bulmak:

# Her iki sunucudan kullanıcı listesi çekin
cut -d: -f1 /etc/passwd | sort > /tmp/sunucu1_users.txt
# Diğer sunucudan SSH ile
ssh sunucu2 "cut -d: -f1 /etc/passwd | sort" > /tmp/sunucu2_users.txt

# Sunucu1'de olup sunucu2'de olmayan kullanıcılar
echo "Sunucu1'e ozgu kullanicilar:"
comm -23 /tmp/sunucu1_users.txt /tmp/sunucu2_users.txt

# Her iki sunucuda da olan kullanıcılar
echo "Ortak kullanicilar:"
comm -12 /tmp/sunucu1_users.txt /tmp/sunucu2_users.txt

Senaryo 4: Log Analizi ile Başarısız Girişimler

Access log’larından dün başarılı giriş yapan kullanıcılarla bugün başarılı giriş yapanları karşılaştırın:

# Dünkü başarılı girişler (basit örnek)
grep "Accepted password" /var/log/auth.log.1 | awk '{print $9}' | sort -u > /tmp/dunku_girisler.txt

# Bugünkü başarılı girişler
grep "Accepted password" /var/log/auth.log | awk '{print $9}' | sort -u > /tmp/bugunku_girisler.txt

# Dün giriş yapıp bugün yapmayan kullanıcılar
echo "=== DUN GIRIS YAPIP BUGUN YAPMAYAN ==="
comm -23 /tmp/dunku_girisler.txt /tmp/bugunku_girisler.txt

# Bugün ilk kez giriş yapan kullanıcılar (dikkat!)
echo "=== BUGUN ILK KEZ GIRIS YAPAN ==="
comm -13 /tmp/dunku_girisler.txt /tmp/bugunku_girisler.txt

Sıralama Konusu: Dikkat Edilmesi Gerekenler

comm kullanırken en sık yapılan hata, sıralanmamış dosyaları vermektir. Bunu aşmanın en kolay yolu process substitution kullanmaktır:

# Dosyaları önceden sıralamak yerine
comm -12 <(sort liste1.txt) <(sort liste2.txt)

Büyük/küçük harf duyarlılığı da önemli bir konudur. Locale ayarlarına göre sıralama farklılaşabilir. Güvenli olmak için:

# Locale bağımsız sıralama
comm -12 <(sort -f liste1.txt) <(sort -f liste2.txt)

# Veya locale'yi tamamen devre dışı bırakın
LC_ALL=C comm -12 <(LC_ALL=C sort liste1.txt) <(LC_ALL=C sort liste2.txt)

comm ile Gelişmiş Kullanım

Çıktıyı Daha Okunabilir Hale Getirmek

Varsayılan tab girintisi bazen kafa karıştırabilir. --output-delimiter seçeneği ile bunu değiştirebilirsiniz:

comm --output-delimiter='|' dosya1.txt dosya2.txt

Ya da çıktıyı etiketleyerek daha anlaşılır hale getirebilirsiniz:

echo "=== SADECE DOSYA1 ==="
comm -23 dosya1.txt dosya2.txt

echo ""
echo "=== SADECE DOSYA2 ==="
comm -13 dosya1.txt dosya2.txt

echo ""
echo "=== ORTAK ==="
comm -12 dosya1.txt dosya2.txt

Script İçinde Kullanım: Otomatik Senkronizasyon Kontrolü

#!/bin/bash
# sync_check.sh - İki dizin arasındaki dosya farkını raporla

KAYNAK="/var/app/config"
HEDEF="/backup/config"
RAPOR="/var/log/sync_rapor.log"

kaynak_liste=$(find "$KAYNAK" -type f | sed "s|$KAYNAK/||" | sort)
hedef_liste=$(find "$HEDEF" -type f | sed "s|$HEDEF/||" | sort)

eksik=$(comm -23 <(echo "$kaynak_liste") <(echo "$hedef_liste"))
fazla=$(comm -13 <(echo "$kaynak_liste") <(echo "$hedef_liste"))
eslesme=$(comm -12 <(echo "$kaynak_liste") <(echo "$hedef_liste"))

echo "=== Sync Raporu: $(date) ===" >> "$RAPOR"
echo "Eslesen dosya sayisi: $(echo "$eslesme" | wc -l)" >> "$RAPOR"

if [ -n "$eksik" ]; then
    echo "UYARI: Yedege gitmeyen dosyalar:" >> "$RAPOR"
    echo "$eksik" >> "$RAPOR"
fi

if [ -n "$fazla" ]; then
    echo "BILGI: Yedekte olup kaynakta olmayan dosyalar:" >> "$RAPOR"
    echo "$fazla" >> "$RAPOR"
fi

comm vs diff: Hangisini Kullanmalısınız?

Bu ikisi farklı işler için tasarlanmıştır:

comm kullanın:

  • Liste karşılaştırmalarında (paket listeleri, kullanıcı listeleri, dosya listeleri)
  • Küme operasyonları istediğinizde (kesişim, fark, birleşim)
  • Satır bazında basit evet/hayır sorularında
  • Script’lerde programatik kullanımda

diff kullanın:

  • Metin dosyalarındaki içerik değişikliklerini görmek istediğinizde
  • Satırın neresinin değiştiğini görmek istediğinizde
  • Patch oluşturmak istediğinizde
  • Sıralı olmayan dosyaları karşılaştırmanız gerektiğinde

Performans Notu

comm son derece hızlı bir araçtır. Milyonlarca satırlık dosyalarda bile diff‘e kıyasla çok daha performanslıdır çünkü sadece sıralı listeyi doğrusal olarak tarar. Büyük log dosyaları veya büyük paket listelerinde bu fark belirgin şekilde hissedilir.

Sonuç

comm komutu, sistem yöneticilerinin araç kutusunda olması gereken ama sıklıkla göz ardı edilen bir utility. Özellikle iki liste arasındaki farkı bulmak, ortak elemanları tespit etmek veya senkronizasyon kontrolü yapmak gibi işlemlerde diff‘e kıyasla çok daha temiz ve anlaşılır sonuçlar üretiyor.

Hatırlamanız gereken birkaç temel nokta:

  • Dosyaların sıralı olması zorunlu, sort komutunu ihmal etmeyin
  • -12, -13, -23 kombinasyonlarını ezberleyin
  • Process substitution (<(komut)) ile çok güçlü one-liner’lar yazabilirsiniz
  • Script’lerde backup kontrolü, paket senkronizasyonu, kullanıcı yönetimi gibi görevler için birebir

Bir sonraki sefer “bu iki liste arasındaki fark nedir?” diye sorduğunuzda, direkt diff‘e atlamadan önce comm‘u düşünün. Çoğu zaman ihtiyacınız olan tam da budur.

About the author

Add comment


KOMUT.IO Başlangıçtan ileri seviyeye, geliştirici ve sysadmin rehberi.

Son yorumlar

Görüntülenecek bir yorum yok.