ฉันต้องการเรียกใช้คำสั่ง Linux ที่จะเปรียบเทียบสองไดเรกทอรีซ้ำและส่งออกเฉพาะชื่อไฟล์ของสิ่งที่แตกต่าง สิ่งนี้รวมถึงสิ่งใดก็ตามที่มีอยู่ในไดเรกทอรีเดียวและไม่ใช่สิ่งอื่นหรือในทางกลับกันและความแตกต่างของข้อความ
ฉันต้องการเรียกใช้คำสั่ง Linux ที่จะเปรียบเทียบสองไดเรกทอรีซ้ำและส่งออกเฉพาะชื่อไฟล์ของสิ่งที่แตกต่าง สิ่งนี้รวมถึงสิ่งใดก็ตามที่มีอยู่ในไดเรกทอรีเดียวและไม่ใช่สิ่งอื่นหรือในทางกลับกันและความแตกต่างของข้อความ
คำตอบ:
จากหน้าคนต่าง:
-q
รายงานเฉพาะว่าไฟล์ต่างกันหรือไม่ไม่ใช่รายละเอียดของความแตกต่าง
-r
เมื่อเปรียบเทียบไดเร็กทอรีให้เปรียบเทียบไดเร็กทอรีย่อยใด ๆ ที่พบซ้ำ
คำสั่งตัวอย่าง:
diff -qr dir1 dir2
ตัวอย่างเอาต์พุต (ขึ้นอยู่กับโลแคล):
$ ls dir1 dir2
dir1:
same-file different only-1
dir2:
same-file different only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2
-x PATTERN
ไว้ในคำสั่งเพื่อแยกไดเรกทอรีย่อยบางอย่าง ตัวอย่างเช่นdiff -qr repo1 repo2 -x ".git"
จะเปรียบเทียบสองไดเรกทอรี แต่จะยกเว้นเส้นทางของไฟล์ด้วย ".git" ในพวกเขา
คุณยังสามารถใช้ rsync
rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
--size-only
จะพลาดขนาดไฟล์เหมือนกัน แต่เนื้อหาที่แตกต่างกันเช่น/ เก่า Version.txt "29a" / ใหม่ Version.txt "29B" ใช้แทน: rsync -ric --dry-run old/ new/
โดยที่อาร์กิวเมนต์ "-i" อนุญาตให้รับรายการไฟล์โดยตรงผ่านrsync -ric --dry-run old/ new/ | cut -d" " -f 2
หากคุณต้องการได้รับรายชื่อไฟล์ที่มีอยู่ในไดเรกทอรีเดียวเท่านั้นไม่ใช่ไดเรกทอรีย่อยและชื่อไฟล์เท่านั้น:
diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'
หากคุณต้องการทำรายการไฟล์และไดเรกทอรีทั้งหมดซ้ำที่มีเส้นทางเต็ม:
diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'
วิธีนี้คุณสามารถใช้คำสั่งต่าง ๆ กับไฟล์ทั้งหมด
ตัวอย่างเช่นฉันสามารถลบไฟล์และไดเรกทอรีทั้งหมดที่อยู่ใน dir1 แต่ไม่ใช่ dir2:
diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}
บนระบบลินุกซ์ของฉันได้รับเพียงแค่ชื่อไฟล์
diff -q /dir1 /dir2|cut -f2 -d' '
audit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
diff -qrN /dir1 /dir2 | cut -f2 -d' '
ทำงานได้ดีสำหรับฉัน!
วิธีการทำงานdiff -qr old/ new/
มีหนึ่งข้อเสียเปรียบที่สำคัญ: มันอาจพลาดไฟล์ในไดเรกทอรีที่สร้างขึ้นใหม่ เช่นในตัวอย่างด้านล่างไฟล์data/pages/playground/playground.txt
ไม่ได้อยู่ในผลลัพธ์ diff -qr old/ new/
ในขณะที่ไดเรกทอรีdata/pages/playground/
คือ (ค้นหาplayground.txtในเบราว์เซอร์ของคุณเพื่อเปรียบเทียบอย่างรวดเร็ว) ฉันยังโพสต์โซลูชันต่อไปนี้ใน Unix & Linux Stack Exchangeแต่ฉันจะคัดลอกที่นี่เช่นกัน:
ในการสร้างรายการไฟล์ใหม่หรือไฟล์ที่ถูกแก้ไขโดยทางโปรแกรมทางออกที่ดีที่สุดที่ฉันสามารถทำได้คือใช้rsync , sortและuniq :
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
ให้ฉันอธิบายด้วยตัวอย่างนี้: เราต้องการเปรียบเทียบ dokuwiki สองรุ่นเพื่อดูว่าไฟล์ใดบ้างที่มีการเปลี่ยนแปลงและไฟล์ใดที่ถูกสร้างขึ้นใหม่
เราดึงข้อมูล tars ด้วย wget และแยกลงในไดเรกทอรีold/
และ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 วิธีหนึ่งอาจพลาดไฟล์ที่สร้างขึ้นใหม่เนื่องจากการเปรียบเทียบ rsync และ diff แสดงที่นี่:
rsync -rcn --out-format="%n" old/ new/
ให้ผลลัพธ์ต่อไปนี้:
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 ในทิศทางเดียวจะไม่ได้รับไฟล์ที่สร้างขึ้นใหม่และอีกวิธีหนึ่งจะทำให้ไฟล์ที่ลบถูกลบไปเปรียบเทียบเอาต์พุตของ diff:
diff -qr old/ new/
ให้ผลลัพธ์ต่อไปนี้:
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 ทั้งสองวิธีและเรียงลำดับผลลัพธ์เพื่อลบรายการที่ซ้ำกันออกเผยให้เห็นว่าไดเรกทอรีdata/pages/playground/
และไฟล์data/pages/playground/playground.txt
นั้นพลาดไปตั้งแต่แรก:
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
ให้ผลลัพธ์ต่อไปนี้:
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
ทำงานด้วยข้อโต้แย้งเหล่านี้:
-r
เพื่อ "เรียกคืนสู่ไดเรกทอรี" -c
เพื่อเปรียบเทียบไฟล์ที่มีขนาดเท่ากันและมีเพียง "ข้ามจากการตรวจสอบไม่ใช่เวลาและขนาด" -n
เพื่อ "ทำการทดลองใช้งานโดยไม่มีการเปลี่ยนแปลง" และ--out-format="%n"
เป็น "การอัพเดตเอาต์พุตโดยใช้ FORMAT ที่ระบุ" ซึ่งเป็น "% n" ที่นี่สำหรับชื่อไฟล์เท่านั้นเอาต์พุต (รายการไฟล์) ของrsync
ทั้งสองทิศทางจะรวมกันและเรียงลำดับโดยใช้sort
แล้วรายการที่เรียงลำดับนี้จะถูกย่อโดยการลบรายการที่ซ้ำuniq
diff new/ old/
) เพื่อดูว่าไดเรกทอรีใดถูกลบไปหรือไม่
diff -qr new/ old/
กับตัวอย่างด้านบนด้วย dokuwiki tars จะสร้างผลลัพธ์เดียวกันกับdiff -qr old/ new/
- เช่นคุณเห็นว่าไดเรกทอรีใหม่ / หายไป แต่ไม่ใช่ไฟล์ที่อยู่ในนั้น
rsync -rvc --delete --size-only --dry-run source dir target dir
diff
หน้า man ใน CentOS 7 อธิบาย-q
ว่า "รายงานเมื่อไฟล์ต่างกัน" ซึ่งมีความชัดเจนน้อยกว่าสิ่งที่คุณเขียน