แตกต่างไปยังเอาต์พุตเฉพาะชื่อไฟล์


244

ฉันต้องการเรียกใช้คำสั่ง Linux ที่จะเปรียบเทียบสองไดเรกทอรีซ้ำและส่งออกเฉพาะชื่อไฟล์ของสิ่งที่แตกต่าง สิ่งนี้รวมถึงสิ่งใดก็ตามที่มีอยู่ในไดเรกทอรีเดียวและไม่ใช่สิ่งอื่นหรือในทางกลับกันและความแตกต่างของข้อความ

คำตอบ:


376

จากหน้าคนต่าง:

-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

ขอบคุณ - diffหน้า man ใน CentOS 7 อธิบาย-qว่า "รายงานเมื่อไฟล์ต่างกัน" ซึ่งมีความชัดเจนน้อยกว่าสิ่งที่คุณเขียน
Chap

2
สิ่งนี้จะเปรียบเทียบเนื้อหาจริงของไฟล์ซึ่งมักเป็นสิ่งที่คนต้องการอย่างไรก็ตามคำตอบ rsync ให้ตัวเลือกเพื่อดูเฉพาะชื่อและขนาดไฟล์ไม่ใช่เนื้อหา บางครั้งก็เป็นที่ต้องการ
steveb

ทำงานบน macOS ได้เช่นกัน
Marius Soutier

นอกจากนี้ยังสามารถรวม-x PATTERNไว้ในคำสั่งเพื่อแยกไดเรกทอรีย่อยบางอย่าง ตัวอย่างเช่นdiff -qr repo1 repo2 -x ".git" จะเปรียบเทียบสองไดเรกทอรี แต่จะยกเว้นเส้นทางของไฟล์ด้วย ".git" ในพวกเขา
ViFI

27

คุณยังสามารถใช้ rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

6
--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
iolsmit

6
นี่เป็นสิ่งที่ดีถ้าคุณกำลังมองหาไฟล์ที่หายไป (โดยเฉพาะในเครือข่ายแชร์) เพราะมันไม่ได้เปรียบเทียบเนื้อหา นี่ช่วยฉันค้นหาไฟล์บางไฟล์ที่ล้มเหลวเมื่อย้ายไปยัง NAS ใหม่
OverZealous

4
ต้องแน่ใจว่ารวมเครื่องหมายสแลชต่อท้ายสำหรับพา ธ ที่ระบุในบรรทัดคำสั่งของ rsync มันจะทำงานไม่ถูกต้องและ rsync จะระบุชื่อไฟล์ทั้งหมด!
Vladimir Panteleev

2
เกี่ยวกับความคิดเห็นที่ไม่ได้ตรวจสอบเนื้อหา บางครั้งสิ่งนี้เป็นที่พึงประสงค์อย่างน้อยที่สุดก็ผ่านครั้งแรก
steveb

13

หากคุณต้องการได้รับรายชื่อไฟล์ที่มีอยู่ในไดเรกทอรีเดียวเท่านั้นไม่ใช่ไดเรกทอรีย่อยและชื่อไฟล์เท่านั้น:

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 {}

9

บนระบบลินุกซ์ของฉันได้รับเพียงแค่ชื่อไฟล์

diff -q /dir1 /dir2|cut -f2 -d' '

7
ฉันไม่ใส่ชื่อไฟล์ด้วยช่องว่างในระบบ linux ของฉัน ;)
gerardw

6
ฉันไม่ได้ตั้งใจที่จะใส่ร้ายคุณ ... ;-p เช่นเดียวกับคำแนะนำสำหรับคนที่ทำ ...
michuelnik

ไม่ได้ผลสำหรับฉัน โครงสร้างไดเรกทอรีของฉันเป็นเหมือนด้านล่างaudit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy

diff -qrN /dir1 /dir2 | cut -f2 -d' 'ทำงานได้ดีสำหรับฉัน!
ฟรานเชสโก

9

วิธีการทำงาน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/) เพื่อดูว่าไดเรกทอรีใดถูกลบไปหรือไม่
Jacques

การทำงานdiff -qr new/ old/กับตัวอย่างด้านบนด้วย dokuwiki tars จะสร้างผลลัพธ์เดียวกันกับdiff -qr old/ new/- เช่นคุณเห็นว่าไดเรกทอรีใหม่ / หายไป แต่ไม่ใช่ไฟล์ที่อยู่ในนั้น
iolsmit

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.