มีไฟล์สองไฟล์เชื่อมโยงกันหรือไม่?


27

ฉันจะบอกได้อย่างไรว่าสองไฟล์เชื่อมโยงกันอย่างหนักจากบรรทัดคำสั่ง? เช่นบางสิ่งบางอย่างเชื่อมโยงสิ่งนี้:

$ ls
fileA fileB fileC

$ is-hardlinked fileA fileB
yes

$ is-hardlinked fileA fileC
no

คำตอบ:


37

สำหรับระบบไฟล์ส่วนใหญ่ file ไฟล์จะถูกกำหนดโดยหมายเลขไอโหนดโดยเฉพาะดังนั้นสิ่งที่คุณต้องตรวจสอบคือไฟล์ทั้งสองมีหมายเลขไอโหนดเดียวกันและอยู่ในระบบไฟล์เดียวกันหรือไม่

แอช ksh, ทุบตีและ zsh มีโครงสร้างที่ไม่ตรวจสอบสำหรับคุณ: -efผู้ประกอบแฟ้มเท่าเทียมกัน

[ fileA -ef fileB ] && ! [ fileA -ef fileC ]

สำหรับกรณีขั้นสูงเพิ่มเติมให้ls -i /path/to/fileระบุหมายเลข inode ของไฟล์ df -P /path/to/fileแสดงให้เห็นว่าระบบไฟล์ใดที่ไฟล์นั้นเปิดอยู่ (หากไฟล์สองไฟล์อยู่ในไดเรกทอรีเดียวกันพวกเขาอยู่ในระบบไฟล์เดียวกัน) หากระบบของคุณมีstatคำสั่งมันอาจจะแสดงหมายเลขไอโหนดและระบบไฟล์ ( statแตกต่างจากระบบไปยังระบบตรวจสอบเอกสารของคุณ) หากคุณต้องการภาพรวมของการเชื่อมโยงฮาร์ดไดรฟ์ภายในไดเรกทอรีให้ลองls -i | sort(อาจส่งไปยัง awk )

ystem ระบบไฟล์ยูนิกซ์ดั้งเดิมทั้งหมดและอีกสองสามอย่างเช่น NTFS แต่อาจไม่ใช่กรณีที่แปลกใหม่อย่าง CramFS


และแน่นอนว่าไม่ได้อยู่ในรูปแบบใดของ FAT ซึ่งจะตรวจพบว่าเป็นไฟล์ "cross-linked"
Ignacio Vazquez-Abrams

4
ทราบว่าfileA -ef fileBยังมีผลตอบแทน0(ความสำเร็จ) ถ้าfileAเป็น symlink ไปfileBหรือในทางกลับกันพวกเขาหรือการเชื่อมโยงทั้งไฟล์เดียวกัน
janmoesen

คุณเรียกใช้คำสั่งที่คุณแนะนำอย่างไร ฉันลอง [.bashrc -ef .bash / .bashrc] และความหลากหลายของสิ่งนี้ แต่มันใช้งานไม่ได้จริง ๆ
Charlie Parker

@CharlieParker [ .bashrc -ef .bash/.bashrc ]ถูกต้อง แน่นอนถ้าไม่มีบริบทฉันก็ไม่รู้ว่าทำไม "ไม่ได้ผลจริง" - คุณสามารถเปรียบเทียบไฟล์ที่ไม่ถูกต้องคุณไม่สามารถตรวจสอบผลลัพธ์ได้อย่างถูกต้องคุณสามารถใช้เชลล์โดยไม่ต้อง-ef...
Gilles 'ดังนั้นจงหยุดความชั่วร้าย'

2
@CharlieParker คำสั่งที่เป็นจริงและเป็นไวพจน์ของ[ testแต่man [หรือman testจะทำให้คุณหน้าคนของคำสั่งภายนอกในขณะที่เพียงเกี่ยวกับทุกเปลือกออกมีมีในตัวคำสั่งกับตัวเลือกที่แตกต่างกันเล็กน้อยดังนั้นคุณต้องมองคนนี้ขึ้นมาในเปลือกของคุณการใช้งาน
Gilles 'หยุดความชั่วร้าย'

4
function is-hardlinked() {
    r=yes
    [ "`stat -c '%i' $1`" != "`stat -c '%i' $2`" ] && r=no
    echo $r
}

6
โปรดทราบว่านี่อาจเป็นผลบวกปลอมหากทั้งสองไฟล์อยู่ในระบบไฟล์ที่ต่างกัน แต่มีไอโหนดเดียวกัน คุณต้องทดสอบหมายเลขอุปกรณ์ด้วย ( stat -c %d) และถ้าคุณอยู่บน Linux (ตามstatคำสั่งของคุณ) เชลล์ของคุณ[ fileA -ef fileB ]จะต้องทำสิ่งนี้ทั้งหมดโดยตรง นอกจากนี้คำสั่งของคุณจะไม่มีการแบ่งชื่อไฟล์ที่มีช่องว่างหรือ\[?*หรือเริ่มต้นด้วย-: ใส่เครื่องหมายอัญประกาศคู่ล้อมรอบคำสั่ง susbtitutions ( "$(stat -c %i -- "$1")") เสมอ
Gilles 'หยุดความชั่วร้าย'

1
เหตุใดคุณจึงต้องใช้โครงสร้างที่ยุ่งยาก แต่พกพาสะดวกแล้วfunctionคำหลักที่ไม่สามารถเคลื่อนย้ายได้โดยใช้ชื่อฟังก์ชันที่ (เนื่องจากมีเครื่องหมายขีดกลาง) ละเมิดข้อตกลง POSIX ในชื่อที่อนุญาต
Charles Duffy

คุณลืมที่จะพูดของคุณและ$1 $2คุณอาจต้องการใช้$()ไวยากรณ์แทน backticks เพราะวงเล็บทำให้ชัดเจนที่คำสั่งเริ่มต้นและที่มันสิ้นสุดและซ้อนได้ง่ายขึ้น
josch

3

ในฐานะผู้โพสต์แรกแนะนำคุณสามารถเขียนสคริปต์ตามสิ่งนี้บน Linux:

stat -c '%i' fileA fileB fileC

4
ไม่เพียงพอ: คุณจะได้รับหมายเลขเดียวกันสำหรับสองไฟล์หากอยู่ในระบบไฟล์ที่แตกต่างกัน แต่มีไอโหนดเดียวกัน คุณต้องทดสอบหมายเลขอุปกรณ์ด้วย ( stat -c %d) และถ้าคุณอยู่บน Linux (ตามstatคำสั่งของคุณ) เชลล์ของคุณ[ fileA -ef fileB ]จะต้องทำสิ่งนี้ทั้งหมดโดยตรง
Gilles 'หยุดความชั่วร้าย'

0

ด้วย GNU find(1)เวอร์ชั่น 4.2.11 หรือใหม่กว่าคุณสามารถใช้สิ่งนี้:

if [ "yes" = "$(find fileA -samefile fileB -exec echo yes \;)" ]; then
    echo yes
else
    echo no
fi

หากfileAเป็นไฟล์เดียวกับfileBแล้วfindจะพิมพ์ "ใช่" และอยู่ในสภาพที่จะกลายเป็นความจริง

ตรงกันข้ามกับการใช้ตัวดำเนินการความเท่าเทียมกันของไฟล์-efสิ่งนี้จะวางไข่กระบวนการใหม่

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