linux diff araçları: değiştirilmiş dosyaların bir listesini oluşturun


14

Linux komut satırı araçlarını kullanarak programlı olarak değiştirilmiş dosyaların listesini nasıl oluştururum? Herhangi bir dosyadaki (delta, yama) farkla ilgilenmiyorum. Sadece önceki ürün sürümüne kıyasla yeni veya değiştirilmiş dosyaların bir listesini almak istiyorum. Böylece yeni bir ürün güncellemesi yayınlayabilirim.

güncelleme: diff -qrçok rahat çıktı üretmiyor. Çıktısının diff -qrda işlenmesi gerekir. Daha iyi bir yol var mı?


"uygun" çıktıya bir örnek nedir?
frogstarr78

Yanıtlar:


8

Bunun için basit bir yaklaşımım var: rsync önizleme modunu kullanın:

rsync -aHSvn --delete old_dir/ new-dir/

Bu komut tarafından "silinecek" olarak gösterilen dosyalar "yeni" dosyalar olacaktır. Devredilecek diğerleri bir şekilde değişti. Daha fazla bilgi için rsync-man-sayfasına bakınız.


13

Diff toool'u kullanabilirsiniz : -q ve -r seçeneklerine bakın

-q  --brief
Output only whether files differ.

-r  --recursive
Recursively compare any subdirectories found.

Misal:

diff -qr dir1 dir2

Kesinlikle korkunç ve okunamayan çıktı, saçma sapan bilgilerle dolu Only in, dizinler ideal kopyalar olsa bile ortaya çıkıyor. Eski bir revizyona karşı değişiklikleri karşılaştırmam ve tüm revizyonu ayrı bir dizine indirmem ve karşılaştırmak için standart SVN araçlarını kullanmam gerekiyordu. Bu gitmek için tek yol gibi görünüyor ...
Hi-Angel

3

diffutilsPaketi içerir lsdiffaracı. Sadece çıkışını diff -ulsdiff'e iletin:

diff -u --other-diff-options path1 path2 | lsdiff

İyi öneri, teşekkür ederim. Miydi patchutilsbenim için paketin (CentOS 5.x).
Steve Kehlet

Evet, Ubuntu / Debian için patchutils paketi de.
artfulrobot

1

Her güncelleme sırasında bir dosyaya dokunurdum ve o zamandan beri değiştirilen dosyaları bulabilirsiniz. find /tree/location -newer /last/update/file -print


1

Yalnızca değiştirdikleri dosyaların adını almak için şu komutu kullanıyorum:

diff -r dirt1 dir2 --brief | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

Bazı dosyaları nesne dosyaları veya kitaplık dosyaları olarak hariç tutmanız gerekirse şunları kullanabilirsiniz:

diff -r dirt1 dir2 --brief --exclude "*.o" --exclude "*.a" | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

1

Programlı olarak yeni veya değiştirilmiş dosyaların bir listesini oluşturmak için gelebileceğim en iyi çözüm rsync , sort ve uniq kullanmaktır :

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Bu örnekle açıklayayım: Hangi dosyaların değiştirildiğini ve hangilerinin yeni oluşturulduğunu görmek için iki dokuwiki sürümünü karşılaştırmak istiyoruz.

Biz wget ile katran getirme ve dizinleri onları ayıklamak old/ve new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

Rsync'i tek yönlü çalıştırmak, yeni oluşturulan dosyaları, rsync ve diff'in karşılaştırması şurada gösterildiği gibi kaçırabilir:

rsync -rcn --out-format="%n" old/ new/

aşağıdaki çıktıyı verir:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

Rsync'i sadece bir yönde çalıştırmak yeni oluşturulan dosyaları özlüyor ve diğer bir yol silinen dosyaları özleyecek, diff'in çıktısını karşılaştıracak:

diff -qr old/ new/

aşağıdaki çıktıyı verir:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

Rsync'i her iki şekilde çalıştırmak ve kopyaları kaldırmak için çıktıyı sıralamak, dizinin data/pages/playground/ve dosyanın data/pages/playground/playground.txtbaşlangıçta kaçırıldığını gösterir:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

aşağıdaki çıktıyı verir:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync şu argümanlarla çalıştırılır:

  • -r "dizinleri tekrarlamak",
  • -c aynı boyuttaki dosyaları karşılaştırmak ve yalnızca "mod-zaman ve boyut yerine sağlama toplamına göre atla",
  • -n "değişiklik yapılmadan deneme sürümü çalıştırması" ve
  • --out-format="%n" yalnızca dosya adı için "% n" olan "belirtilen FORMAT kullanarak güncellemeler çıktısını alma"

Her rsynciki yönde çıktı (dosya listesi) kullanılarak birleştirilir ve sıralanır sortve bu sıralanan liste daha sonra tüm kopyalar kaldırılarak yoğunlaştırılır.uniq


0

Aşağıdakileri kullanarak istenen sonucu almalısınız:

diff -r --brief dir1/ dir2/

0

Bu hile yapabilir:

compare_dirs()
{
    # Shows which files and directories exist in one directory but not both
    if [ $# -ne 2 ]
    then
        echo "Usage: compare_dirs dir1 dir2" >&2
        return 2
    fi
    for path
    do
        if [ ! -d "$path" ]
        then
            echo "Not a directory: $path" >&2
            return 1
        fi
    done
    comm -3 \
        <(cd -- "$1" && find . -printf '%P\0' | sort -z | quote_shell) \
        <(cd -- "$2" && find . -printf '%P\0' | sort -z | quote_shell)
}

0

Normalde dosyaları SubVersion veya git gibi bir çeşit sürüm kontrol sistemine koyarsınız, çünkü bunlar bunu sizin için kutudan çıkarabilir.

Ancak dir1 üzerinde bir for döngüsü ile hızlı bir komut dosyası yapabilir ve daha sonra her dosyayı dir2'deki dosyayla karşılaştırabilirsiniz. For döngüsü dosyaların farklı olup olmadığını bilmek diff çıkış koduna bakabilirsiniz.

Belki böyle bir şey:

for f in `(cd dir1 ; find .)`
do 
  diff $f ../dir2/$f
  if [ "$?" == "0" ]
  then 
    echo same
  else 
    echo diff: $f
  fi
done

Not: Komut dosyası test edilmediğinden, yukarıdaki örnek "bash esinlenilmiş sözde kodu" ...


Hadi başka gidelim ama git ile

Oynatılacak bazı örnek dosyalar oluşturun

mkdir -p dir1/test1/test11
mkdir -p dir1/test1/test12
mkdir -p dir1/test1/test13
echo "Test1" >> dir1/test1/test11/t1.txt
echo "Test2" >> dir1/test1/test12/t2.txt
echo "Test3" >> dir1/test1/test13/t3.txt

#And a dir to work in
mkdir gitdir

Ardından dir ve import dir1 değerlerini girin

cd gitdir/
git init .
cp -r ../dir1/* .
git add .
git commit -m 'dir1'

Dışarı çıkın ve dir1'i değiştirin (böylece dir2'niz olur)

cd ..
echo "Test2" > dir1/test1/test11/t1.txt

Sonra git dir'e gidin ve yeni dizini içe aktarın

cd gitdir/
cp -r ../dir1/* .

Şimdi git'e neyin değiştiğini sorun (status komutuyla)

git status -s

Çıktı, aşağıdaki gibi görünen değişikliklerin yer aldığı bir listedir:

 M test1/test11/t1.txt

0

Belki farklı bir şeyle daha mutlu olursun. Deneyin git.

Bunu örnek olarak yapın:

mkdir a
cd a
git init
touch b
git add . && git commit -m "Empty file"
git status
echo c >> b
git status
git add . && git commit -m "Full file"
git status

gitdosyalarınızı sizin için izleyecektir. Komut git statussize son işlemden bu yana değiştirilen tüm dosyaları gösterir.


0

Bu rsync'e benzer : hedefteki daha yeni dosyanın ne zaman yazılacağını göster (daha sonra sorulsa da yinelenmez).

Soruda belirtildiği gibi, "diff -q -r" bazı işlemlerin yararlı olmasını gerektirebilir. Soru, çıktının biçimini belirtmedi; cevaplar farklı raporlar verir.

rsyncbu amaç için yararlı bir araçtır çünkü çok daha hızlıdır diff. Ancak @nils tarafından önerilen çözüm, eski / yeni dizin ağaçları arasındaki gerçek farklardan çok daha ayrıntılıdır (ve daha fazla dosya listeler). Örneğin, bu yanıt için yazdığım komut dosyasıyla karşılaştırıp aynı veriler üzerinde çalışıyor,

  • @nils answer 605 satır üretir (görünüşe göre dizin değişikliklerini içerdiği için ),
  • "diff -q -r" birkaç dakika çalıştıktan sonra 352 satır üretir ve
  • betiğim 252 satır gösteriyor ( gerçek dosyalar değiştirildi, eklendi veya silindi)

Yapmak için diffiçin doğru hesabına yeni dosyalar, ihtiyacınız -N(ı önerdi cevapların hiçbirinde görmüyorum olan) yanı seçeneği. Bununla birlikte, çok daha yavaş (büyüklük sıraları) olduğundan rsync, ikincisinin çıktısını iyileştirmek için bir yol gibi görünüyor.

daha fazla okuma


0

Her zaman sha1sum'a kısmi oldum (hatta md5sum; bu bağlamda oldukça güvenlidir).

find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/before
# don't miss the "sort" in there; it's important

# (later)
find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/after
vimdiff /tmp/before /tmp/after
# or whatever diff tool you like, even "diff -u"

Bazen - yeniden adlandırılmakta veya taşınmak için çok fazla dosyanız varsa - ilk alanda sıralama yapmak ve sonra fark yapmak yardımcı olabilir, ancak çoğu zaman bu yeterince iyidir.

Diğer yöntemlerden bazılarıyla karşılaştırıldığında, bunun "önce" dosyalarının bir kopyasını saklamanız gerekmediğini unutmayın; yalnızca md5sum çıktı dosyası.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.