ยกเว้นไดเรกทอรีในการค้นหาการค้นหา


14

การค้นหาด้วยlocateค้นหาพา ธ ในระบบไฟล์
บ่อยครั้งที่คุณรู้ว่าคุณมีความสนใจในไฟล์อย่างใดอย่างหนึ่งเท่านั้นหรือไดเรกทอรีเท่านั้น
การค้นหา 'ค้นหา' มักจะส่งคืนผลลัพธ์จำนวนมาก มันจะมีประโยชน์ที่จะรวมเพียงหนึ่งประเภทในผลลัพธ์เพราะจะช่วยให้ผลผลิตสั้นลง

แต่มีข้อโต้แย้งที่น่าสนใจที่จะทิ้งไฟล์หรือไดเรคทอรีไว้อย่างใดอย่างหนึ่งเนื่องจากรายการของพา ธ ผลลัพธ์สามารถคลุมเครือไม่เพียง แต่ในทางทฤษฎี

ตัวอย่างด้านล่างเป็นกรณีของโลกแห่งความจริงและไม่ผิดปกติ:

$ locate --regex --basename "xfce4-keyboard-overlay$"
/usr/local/bin/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay

ตกลงเราพบบางอย่าง! แต่ ... ไฟล์หรือไดเรกทอรี?

$ file /usr/local/bin/xfce4-keyboard-overlay 
/usr/local/bin/xfce4-keyboard-overlay:   bash script

นั่นคือไฟล์ ...

$ file /usr/local/share/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay: directory

ในขณะที่สองไม่ใช่

ความคลุมเครือนี้คือการทำให้รายการยาวของเส้นทางยากที่จะอ่านดังนั้นมันจะดีจริงๆไดเรกทอรีกรองออกเช่นใช้ตัวเลือกบรรทัด comman locateสำหรับ

สิ่งนี้มีอยู่จริงหรือไม่? แม้ว่าตัวกรองสำหรับไดเรกทอรีแยกจากการค้นหาหรือไม่

อย่างน้อยหนึ่งสามารถใช้สคริปต์เพื่อวนซ้ำชื่อไฟล์ทั้งหมดเพื่อตรวจสอบ - ซึ่งอาจช้า

คำตอบ:


3

ด้วยzsh:

print -rl ${(0)^"$(locate -0 ...)"}(N.)

(0)เป็นธงขยายตัวพารามิเตอร์ที่แยกตัวอักษร NUL (ที่เราใช้locate -0) (ps:\0:)สั้นสำหรับ

ด้วย^แทนที่จะเพิ่ม(N.)ที่ส่วนท้ายของอาร์เรย์เราเพิ่มเข้าไปในแต่ละองค์ประกอบ

(N.)เป็นตัวระบุแบบกลม, .เพื่อจับคู่ไฟล์ทั่วไปเท่านั้น, Nเพื่อลบองค์ประกอบหากมันไม่ตรงกัน (ไม่มีอยู่หรือไม่ใช่ไฟล์ปกติหรือเราไม่สามารถตรวจสอบได้) คุณยังสามารถใช้^/แทน.เพื่อจับคู่กับที่ไม่ใช่ไดเรกทอรีแทนไฟล์ปกติเท่านั้น

print -rlพิมพ์แต่ละอาร์กิวเมนต์ดิบในการแยกสาย

คุณสามารถใช้ตัวระบุแบบzshหมุนรอบใดก็ได้แต่โปรดทราบว่าตัวเรียงลำดับจะไม่มีผลกระทบใด ๆ เนื่องจากเรากำลังขยายตัวหนึ่งตัวต่อหนึ่งไฟล์ที่นี่ดังนั้นจึงมีเพียงหนึ่งไฟล์ที่จะเรียงลำดับสำหรับแต่ละตัว

(โปรดทราบว่าอาจล้มเหลวหากไฟล์ล่าสุดรายงานโดยlocateสิ้นสุดในอักขระบรรทัดใหม่ (คำสั่งทดแทนการแสดงคำสั่งผิดพลาดในทุกเชลล์))


3

นี่เป็นเรื่องไม่สำคัญเท่าคำตอบอื่น ๆ แต่อาจมีประสิทธิภาพน้อยลง:

locate --regex --basename "xfce4-keyboard-overlay$" | 
        while IFS= read -r f; do [ -f "$f" ] && printf "%s\n" "$f"; done

(แยกออกเป็นสองบรรทัดเพื่อให้สามารถอ่านได้) ด้านบนจะจัดการกับชื่อที่มีช่องว่าง IFS=ดูเหมือนว่าจะมีความจำเป็นที่จะจับกับชื่อต่อท้ายช่องว่างและของหลักสูตรที่-rช่วยให้คุณจัดการกับเครื่องหมาย

วิธี“ ลองlocateเข้าไปในบางสิ่งบางอย่าง” อาจจะล้มเหลวหากชื่อพา ธ ที่มีการขึ้นบรรทัดใหม่ปรากฏขึ้น


สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการIFSอ่านsh(1)หรือbash(1) (โดยการพิมพ์man shหรือman bashในระบบระวัง * และ / หรือการอ่านมันนี่ , ที่นี่ , ที่นี่ , และ / หรือที่นี่ ) จากนั้นอ่านทำความเข้าใจ IFS และBash: อ่านทีละบรรทัดโดยใช้ IFSบน Stack Exchange (เน้นที่คำตอบที่มีคะแนนมากกว่า 5 โหวต) และหากคุณยังมีไม่เพียงพอให้ลองดูIFSจากผลการค้นหาWiki ของ IIG และGreg บน Bash Hackers Wiki (ไม่ใช่ใน Exchange Exchange)


คุณสามารถเพิ่มข้อมูลบางอย่างเกี่ยวกับสิ่งที่ "IFS =" หลังจากที่whileคำสั่งของคุณไม่?
เบิ

ฉันทำไปแล้ว
G-Man กล่าวว่า 'Reinstate Monica'

แบ็กสแลชจะยังคงมีปัญหากับการใช้ echo มากมาย คุณควรใช้printfข้อมูลโดยพลการ
Stéphane Chazelas

อาจจะมีวิธีการแก้ปัญหาการขึ้นบรรทัดใหม่ของคุณโดยใช้พารามิเตอร์ "--null" เพื่อlocateและเพิ่มของคุณreadเป็นข้อเสนอแนะที่นี่transnum.blogspot.ie/2008/11/...
โรเบิร์ต

@ StéphaneChazelas: จุดดี แก้ไขแล้ว.
G-Man กล่าวว่า 'Reinstate Monica'

2
locate --null --regex --basename "xfce4-keyboard-overlay$" |
  xargs -r0 sh -c 'find "$@" -prune ! -type d' sh

ที่จริงมันสกปรกกว่าที่ดู ... แต่เป็นการตรวจสอบที่ดี สมมติว่ามันเป็น pseudocode จากนั้นมันจะมีประโยชน์ :)
Volker Siegel

1
@Volker: ฉันยอมรับว่ามันไม่ดี: มันจะแสดงรายการ/usr/local/share/xfce4-keyboard-overlay และทุกไดเรกทอรีย่อยในตัวอย่างของคุณ การเพิ่มความ-maxdepth 0ช่วยเหลือ
G-Man กล่าวว่า 'Reinstate Monica'

มันจะไปได้ดียิ่งขึ้น ... : D locate --regex --basename "xfce4-keyboard-overlay$" | xargs -I % sh -c "test -d % && echo %"
FloHimself

1
ใช้xargsกับfindเป็นความคิดที่ดีฉันได้แก้ไขเพื่อให้แข็งแกร่ง หวังว่าคุณจะไม่รังเกียจ
Stéphane Chazelas

1

xargsจะทำซ้ำคำสั่งสำหรับแต่ละบรรทัดหากคุณระบุ-L 1หรือ-iพารามิเตอร์

ดูที่นี่

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i bash -c '(test -d "{}" && echo "{}")'

เป็นที่ยอมรับกันว่ามันคือการเตะเชลล์ใหม่สำหรับแต่ละไฟล์ แต่มันก็มีข้อดีของการเป็นคนดีและกะทัดรัด

แก้ไข:ฉันไม่ค่อยพอใจกับคำตอบนั้นเพราะมันเป็นการเตะเชลล์ใหม่สำหรับแต่ละไฟล์ สิ่งนี้ควรมีเพียงสองกระบวนการ:

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i echo 'test -d "{}" && echo "{}"' | bash

แน่นอนว่ามันจะดีถ้าเราหลีกเลี่ยงการเตะล่ามไปพร้อมกัน แต่xargsดูเหมือนว่าจะเป็นอุปสรรคในการสั่งการลูกโซ่


3
อันนั้นเพิ่งรีบูทเครื่องของฉัน (มีไฟล์ที่เรียกว่า/home/evil/$(reboot)/xfce4-keyboard-overlayและฉันก็วิ่งแบบนั้นอย่างโง่root)
Stéphane Chazelas

2
@ StéphaneChazelas +1 สำหรับความกล้าหาญที่จะเรียกใช้ "รหัสสุ่มจาก internets" เป็นราก;) (scnr)
Volker Siegel

0

สองเซ็นต์ของฉัน:

while IFS= read i; \
do \
  if [ -f "$i" ]; \
  then \
    echo "$i"; \
  fi; \
done < <(locate --regex --basename "xfce4-keyboard-overlay$")

นี่เป็นวิธีที่ G-Man รวมเข้ากับการทดแทนกระบวนการมากขึ้นหรือน้อยลง


ที่จริงแล้วนี่เป็นวิธีที่ฉันทำมากขึ้นหรือน้อยลงเมื่อรวมกับการทดแทนกระบวนการลบด้วยความสามารถในการจัดการชื่อไฟล์ที่มีแบ็กสแลชหรือมีช่องว่างสีขาวต่อท้าย นอกจากนี้โปรดทราบว่าชื่อคำถามระบุว่า "ไม่รวมไดเรกทอรี" และคำตอบนี้มีเฉพาะไดเรกทอรี
G-Man กล่าวว่า 'Reinstate Monica'

ขอโทษ ความผิดพลาดของฉัน. การแก้ไข
Tristan Storch

-1

ถ้าคุณรวมlocateกับfileและgrep? ...

$ for f in `locate --regex --basename "xfce4-keyboard-overlay$"`; do file $f; done | grep -vi directory

ฉันไม่ได้ทดสอบ แต่ฉันคิดว่ามันอาจช้าเพราะมันสร้างกระบวนการfileสำหรับทุก ๆ เส้นทาง โปรดทราบว่ามักจะมีผลลัพธ์หลายบรรทัดสำหรับการค้นหา การทดสอบปัจจุบันของฉันกำลังค้นหา "gnome" ซึ่งให้เส้นทางประมาณ 73,000 เส้นทางเพื่อทดสอบ
Volker Siegel

2
@Volker: มันแย่ไปกว่านั้นสำหรับทุก$fที่เป็นไฟล์ที่fileโปรแกรมจะเปิดไฟล์ที่และอ่านจากมัน stat()นี้มีราคาแพงสักนิดเมื่อสิ่งที่คุณต้องทำคือ …………นอกจากนี้สิ่งนี้จะให้ผลลัพธ์ที่ไม่ถูกต้องสำหรับไฟล์ที่มี“ ไดเรกทอรี” อยู่ในชื่อ (เช่น "phone_directory") ……………… (นอกจากนี้for f in `…`; do …ไวยากรณ์ไม่สามารถจัดการชื่อที่มีช่องว่างได้)
G-Man พูดว่า 'Reinstate Monica'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.