linux diff tools: buat daftar file yang dimodifikasi

14

Bagaimana cara membuat daftar file yang dimodifikasi secara terprogram menggunakan alat baris perintah linux? Saya tidak tertarik dengan perbedaan pada file tertentu (delta, patch). Saya hanya ingin memiliki daftar file baru atau yang dimodifikasi dibandingkan dengan rilis produk sebelumnya. Sehingga saya dapat menerbitkan pembaruan produk baru.

pembaruan: diff -qrtidak menghasilkan keluaran yang sangat nyaman. Output diff -qrjuga perlu diproses. Apakah ada cara yang lebih baik?

Alpha Sisyphus
sumber
apa contoh output "nyaman"?
frogstarr78

Jawaban:

8

Saya punya pendekatan sederhana untuk ini: Gunakan mode rsync-preview:

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

File yang ditampilkan sebagai "akan dihapus" oleh perintah itu akan menjadi file "baru". Yang lain yang akan ditransfer telah berubah dalam beberapa cara. Lihat halaman man-rsync untuk detail lebih lanjut.

Nils
sumber
13

Anda dapat menggunakan diff toool: lihat opsi -q dan -r

-q  --brief
Output only whether files differ.

-r  --recursive
Recursively compare any subdirectories found.

Contoh:

diff -qr dir1 dir2
stivlo
sumber
Output yang benar-benar mengerikan dan tidak dapat dibaca, berantakan dengan informasi omong kosong mengatakan Only inyang muncul bahkan jika direktori adalah salinan yang ideal. Saya diperlukan untuk membandingkan perubahan terhadap revisi lama, dan akhirnya mengunduh seluruh revisi ke direktori terpisah, dan menggunakan alat SVN standar untuk membandingkan. Itu sepertinya satu-satunya cara untuk pergi ...
Hi-Angel
3

The diffutilspaket termasuk lsdiffalat. Cukup berikan output diff -uke ke lsdiff:

diff -u --other-diff-options path1 path2 | lsdiff
ninjalj
sumber
Saran yang bagus, terima kasih. Ada dalam patchutilspaket untuk saya (CentOS 5.x).
Steve Kehlet
Yap, paket patchutils untuk Ubuntu / Debian juga.
artfulrobot
1

Saya hanya akan menyentuh file pada saat setiap pembaruan, dan kemudian Anda dapat menemukan file yang dimodifikasi sejak saat itu dengan find /tree/location -newer /last/update/file -print

Paul Tomblin
sumber
1

Untuk hanya mengambil nama file yang diubah, saya menggunakan perintah ini:

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

Jika perlu mengecualikan beberapa file sebagai file objek atau file perpustakaan, Anda dapat menggunakan:

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

Untuk membuat daftar file baru atau yang dimodifikasi secara terprogram solusi terbaik yang dapat saya buat adalah menggunakan rsync , sortir , dan uniq :

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

Mari saya jelaskan dengan contoh ini: kami ingin membandingkan dua rilis dokuwiki untuk melihat file mana yang diubah dan mana yang baru dibuat.

Kami mengambil ter dengan wget dan mengekstraknya ke direktori old/dan 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

Menjalankan rsync salah satu cara mungkin kehilangan file yang baru dibuat karena perbandingan rsync dan diff ditampilkan di sini:

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

menghasilkan output berikut:

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

Menjalankan rsync hanya dalam satu arah melewatkan file yang baru dibuat dan sebaliknya akan kehilangan file yang dihapus, bandingkan output dari diff:

diff -qr old/ new/

menghasilkan output berikut:

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

Menjalankan rsync baik cara dan mengurutkan output untuk menghapus duplikat mengungkapkan bahwa direktori data/pages/playground/dan file data/pages/playground/playground.txtawalnya tidak terjawab:

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

menghasilkan output berikut:

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 Dijalankan dengan argumen tesis:

  • -r untuk "berulang ke direktori",
  • -c untuk juga membandingkan file dengan ukuran identik dan hanya "lewati berdasarkan checksum, bukan mod-time & size",
  • -n untuk "melakukan uji coba tanpa perubahan yang dibuat", dan
  • --out-format="%n" ke "keluaran pembaruan menggunakan FORMAT yang ditentukan", yaitu "% n" di sini hanya untuk nama file

Output (daftar file) dari rsynckedua arah digabungkan dan diurutkan menggunakan sort, dan daftar yang diurutkan ini kemudian diringkas dengan menghapus semua duplikat denganuniq

iolsmit
sumber
0

Anda harus mendapatkan hasil yang diinginkan menggunakan:

diff -r --brief dir1/ dir2/
Marcin Gil
sumber
0

Ini mungkin melakukan trik:

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)
}
l0b0
sumber
0

Biasanya Anda meletakkan file ke dalam semacam sistem kontrol versi seperti SubVersion atau git, karena mereka dapat melakukan ini untuk Anda di luar kotak.

Tapi Anda bisa melakukan skrip cepat dengan for loop di dir1 dan kemudian membandingkan setiap file dengan yang ada di dir2. Untuk loop dapat melihat kode keluar dari diff untuk mengetahui apakah file berbeda.

Mungkin kira-kira seperti ini:

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

Catatan: Script tidak diuji, jadi contoh di atas adalah "bash terinspirasi pseudocode" ...


Mari kita lakukan lagi tetapi dengan git

Buat beberapa file contoh untuk dimainkan

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

Kemudian masukkan dir dan impor dir1

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

Keluar dan modifikasi dir1 (jadi itu dir2 Anda)

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

Lalu masuk ke git dir dan impor dir baru

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

Sekarang tanyakan git apa yang telah berubah (dengan perintah status)

git status -s

Outputnya adalah daftar dengan perubahan, yang terlihat seperti ini:

 M test1/test11/t1.txt
Johan
sumber
0

Mungkin Anda akan lebih bahagia dengan sesuatu yang berbeda. Coba git.

Lakukan ini sebagai contoh:

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

gitakan melacak file Anda untuk Anda. Perintah git statusakan menunjukkan kepada Anda semua file yang telah dimodifikasi sejak komit terakhir.

bahamat
sumber
0

Ini mirip dengan rsync: menunjukkan kapan file yang lebih baru pada tujuan ditimpa (ditanyakan kemudian, meskipun bukan duplikat).

Seperti ditunjukkan dalam pertanyaan, "diff -q -r" mungkin memerlukan beberapa pemrosesan agar bermanfaat. Pertanyaannya tidak menentukan bentuk output; jawabannya memberikan berbagai jenis laporan.

rsyncadalah alat yang berguna untuk tujuan ini karena jauh lebih cepat daripada diff. Namun solusi yang disarankan oleh @nils jauh lebih verbose (dan daftar lebih banyak file) daripada perbedaan aktual antara pohon direktori lama / baru. Misalnya, membandingkannya dengan skrip yang saya tulis untuk jawaban itu, dan berjalan pada data yang sama,

  • @nils answer menghasilkan 605 baris (tampaknya karena itu termasuk perubahan direktori ),
  • "diff -q -r" menghasilkan 352 baris setelah dijalankan selama beberapa menit, dan
  • skrip saya menunjukkan 252 baris ( file aktual diubah, ditambahkan atau dihapus)

Untuk membuat diffakun baru dengan benar untuk file - file baru , Anda juga perlu -Nopsi (yang saya tidak melihat di salah satu jawaban yang disarankan). Namun, karena jauh lebih lambat (urutan besarnya) daripadarsync , meningkatkan output yang terakhir tampaknya cara untuk pergi.

Bacaan lebih lanjut

Thomas Dickey
sumber
0

Saya selalu menyukai sha1sum (atau bahkan md5sum; dalam konteks ini cukup aman).

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"

Terkadang - seperti jika Anda memiliki terlalu banyak file yang diubah namanya atau dipindahkan - mengurutkan pada bidang pertama dan kemudian melakukan diff bisa membantu, tetapi sebagian besar waktu ini cukup baik.

Perhatikan bahwa, dibandingkan dengan beberapa metode lain, ini memiliki keuntungan bahwa Anda tidak perlu menyimpan salinan file "sebelum"; hanya file output md5sum.

sitaram
sumber