ค้นหาไดเรกทอรีย่อยสิ้นสุดทั้งหมดในทรี


11

รับโครงสร้างต่อไปนี้:

oz123@debian:~/ $ tree .
.
├── a
│   ├── a1
│   ├── a2
│   └── a3
├── a1
│   ├── a11
│   ├── a12
│   └── a31
├── b
│   └── b1
│       ├── b11
│       │   └── b21
│       │       └── b31
│       ├── b12
│       └── b3
└── c

16 directories, 0 files

ฉันจะค้นหาโหนดปลายทางทั้งหมดได้อย่างไร

ฉันพบวิธีแก้ไขปัญหาต่อไปนี้ซึ่งดูเหมือนจะดี แต่ฉันต้องพิสูจน์ว่าไม่มีกรณีทดสอบที่จะล้มเหลว

หน้าช่วยเหลือของ-linksรัฐ:

คุณยังสามารถค้นหาไฟล์ที่มีลิงค์จำนวนหนึ่งด้วย '-links' ไดเรกทอรีปกติมีลิงก์อย่างน้อยสองลิงก์ ของพวกเขา รายการที่สอง หากพวกเขามีไดเรกทอรีย่อยแต่ละคนยังมีฮาร์ดลิงก์ที่เรียกว่า .. ไปยังไดเรกทอรีหลัก การ และ .. รายการไดเร็กทอรีจะไม่ถูกค้นหาตามปกติยกเว้นว่ามีการกล่าวถึงในบรรทัดคำสั่ง find

ทางออกที่เป็นไปได้:

oz123@debian:~/ $ find .  -type d  -links 2
./a/a2
./a/a3
./a/a1
./c
./a1/a31
./a1/a11
./a1/a12
./b/b1/b12
./b/b1/b3
./b/b1/b11/b21/b31
  • ทุกคนสามารถให้ทางออกที่ดีกว่า (โดยไม่ต้องใช้ท่อและ sed นี่เป็นนักแสดง ... )
  • มันจะทำงานกับระบบไฟล์ใด ๆ

3
คุณจะไม่พบนักแสดงมากกว่า-links 2กลอุบาย btrfsมันจะไม่ทำงานใน
Stéphane Chazelas

คำตอบ:


3

นอกเหนือจากโซลูชันของคุณด้วย-linksฉันต้องการเพิ่มว่ามันจะไม่ทำงานบนระบบไฟล์ที่ไม่ปฏิบัติตามข้อตกลงการเชื่อมโยงไดเรกทอรี Unix จากman findตัวเลือก-noleafเหล่านี้เป็นอย่างน้อย CD-ROM, ระบบไฟล์ MS-DOS และจุดเชื่อมต่อไดรฟ์ข้อมูล AFS

สำหรับการอ้างอิงคำถามนี้มีการพูดคุยกับโซลูชั่นที่แตกต่างกันซึ่งช้ากว่าจริง ๆ และมักหันไปใช้ท่อเพื่อ sed / awk และคล้ายกัน


3

มีตัวเลือกที่ชัดเจนกว่านี้เล็กน้อย-empty:

find . -type d -empty

UPD ตกลงคุณถูกวิธีนี้จะไม่ทำงานกับไฟล์ใน dirs

ดังนั้นที่นี่มันเป็นระบบไฟล์คงที่รุ่นที่ไม่สามารถพึ่งพาได้:

find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \;

2
หากฉันเข้าใจคำถามไดเรกทอรีปลายทางอาจมีไฟล์อยู่ สิ่งนี้จะไม่พิมพ์ไดเรกทอรีเหล่านั้นเนื่องจากพวกเขาจะไม่ "ว่างเปล่า" ...
Stefan

@rush, ตำบลสามารถว่างเปล่าได้หรือไม่
Oz123

@ Oz123 โปรดตรวจสอบการอัปเดตของฉันมันควรจะเร็วพอ แต่ช้ากว่าเล็กน้อยเมื่อเทียบกับวิธีการของคุณ
เร่ง

@ เร่งขอบคุณ แต่ฉันต้องหลีกเลี่ยงท่อจริงๆพวกเขาสามารถทำให้สิ่งต่าง ๆ ช้าลง
Oz123

1

find . -type d -links 2ทำงานได้กับระบบไฟล์ส่วนใหญ่ แต่ไม่ทั้งหมด ฉันไม่คิดว่าจะมีวิธีอื่นนอกเหนือจากการรู้ว่าระบบไฟล์ชนิดใดมีคุณสมบัติที่ไดเรกทอรีมีลิงก์ไปยังตัวเอง GNU ค้นหาตรวจพบสิ่งนี้แบบไดนามิก (หากพิมพ์บางอย่างเกี่ยวกับ“ การเปิดตัวเลือก -noleaf ของ find โดยอัตโนมัติ” คุณจะรู้ว่าระบบไฟล์ของคุณไม่มีคุณสมบัตินี้) ประเภทระบบไฟล์ทั่วไปส่วนใหญ่นั้นใช้ได้ แต่ไม่ใช่ FAT หรือ btrfs

หากคุณต้องการแน่ใจคุณจะต้องทดสอบแต่ละไดเรกทอรี วิธีหนึ่งในการทำเช่นนี้คือเรียกใช้findอีกครั้งสำหรับแต่ละไดเรกทอรีย่อย

find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print

(ด้วย GNU findคุณสามารถแทนที่-pruneด้วย-print -quitเพื่อให้มีประสิทธิภาพมากขึ้นเล็กน้อย)

findอีกวิธีหนึ่งคือการโพสต์ขั้นตอนการส่งออกของ ด้วยfind -depthไดเร็กทอรีใบไม้คือไดเร็กทอรีที่ไม่เป็นไปตามไดเร็กทอรีย่อยของตัวเอง

find . -depth -type d -print0 |
awk -v RS='\0' '
    substr(previous, 1, length($0) + 1) != $0 "/"
    { previous = $0 }
'

0

ลองวิธีแก้ปัญหาต่อไปนี้ (ควรรองรับ Linux, Unix และ OS X):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';'

มันเป็นวิธีการที่คล้ายกันในการเร่งแก้ปัญหาแต่ไม่มีท่อใด ๆ

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