ฉันจะแสดงรายการทุกไฟล์ในไดเรกทอรียกเว้นไฟล์ที่มีนามสกุลที่ระบุได้อย่างไร


28

สมมติว่าฉันมีโฟลเดอร์ที่มี. txt , .pdfและไฟล์อื่น ๆ ฉันต้องการแสดงรายการไฟล์ "อื่น ๆ " (เช่นไฟล์ที่ไม่มีนามสกุล. txtหรือ. pdf ) คุณมีคำแนะนำเกี่ยวกับวิธีการทำเช่นนี้หรือไม่?

ฉันรู้วิธีแสดงรายการไฟล์ที่ไม่มีส่วนขยายที่กำหนด ตัวอย่างเช่นหากฉันต้องการแสดงรายการไฟล์ทั้งหมดยกเว้นไฟล์. txtให้เลือกเช่นกัน

find -not -iname "*.txt"

หรือ

ls | grep -v '\.txt$' | column

ดูเหมือนจะทำงาน แต่ฉันจะแสดงรายการทุกอย่างยกเว้นไฟล์. txt หรือ ไฟล์. pdf ได้อย่างไร มันดูเหมือนว่าฉันต้องใช้การจัดเรียงของตรรกะ "หรือ" บางอย่างในหรือfindgrep


2
โปรดทราบว่าพฤติกรรมของlsvs findvs globbing อาจแตกต่างกันสำหรับ dotfiles ที่ซ่อนอยู่
jw013

1
สิ่งที่จะต้องเก็บไว้ในใจ: findจะสำรวจไดเรกทอรีย่อยเช่น lsrecursive ใช้-maxdepth 1กับที่จะได้ไปทำงานมากขึ้นเช่นfind ls
jw013

ดังนั้นไม่วนซ้ำเพียงรายการไฟล์ใน dir ปัจจุบัน?
เดซี่

คำตอบ:


28

สมมติว่ามีรุ่นที่เหมาะสมlsนี่อาจเป็นวิธีที่ง่ายที่สุด:

ls -I "*.txt" -I "*.pdf"

หากคุณต้องการทำซ้ำในไดเรกทอรีย่อยทั้งหมด:

ls -I "*.txt" -I "*.pdf" -R

8
lsตัวเลือกGNU ไม่ใช่แบบพกพา
bahamat

4
lsไม่ได้เป็นของสคริปต์แบบพกพาจริงๆแล้วดังนั้นฉันจึงสมมติว่า OP จะถามเกี่ยวกับการใช้แบบโต้ตอบเท่านั้น
jw013

1
ทำไม ls ไม่พกพาได้ ฉันควรใช้อะไรดี
Freedo

28

ค้นหาการสนับสนุน -o

find . ! '(' -name '*.txt' -o -name '*.pdf' ')'

คุณต้องใช้วงเล็บเพื่อทำให้ลำดับความสำคัญถูกต้อง ค้นหาทำสิ่งต่างๆมากมาย ฉันแนะนำให้อ่านผ่าน manpage ของมัน

คุณยังสามารถทำสิ่งใดสิ่งหนึ่งหรือในgrep(แต่จริงๆแล้วคุณไม่ควรแยกเอาท์พุทของls )

ls | grep -Ev '\.(txt|pdf)$' | column

1
ขอบคุณ! ทำไมฉันจึงไม่ควรแยกการส่งออกของls?
Andrew

6
@Andrew ก่อนเพราะมันเปราะบาง (พิจารณาชื่อไฟล์ที่มีบรรทัดใหม่ในนั้น - ใช่นั่นคือชื่อไฟล์ที่ถูกต้อง - find's -print0 / -exec / -delete / etc หลีกเลี่ยงปัญหานั้น); ที่สองเพราะโดยปกติจะมีวิธีที่ง่ายกว่า
Derobert

นอกจากนี้ยังมีfindmanpage ผมบริสุทธิ์ใจแนะนำ Unix พลังงานบทความเกี่ยวกับเครื่องมือfindเช่นdocstore.mik.ua/orelly/unix3/upt/ch09_06.htmและdocstore.mik.ua/orelly/unix3/upt/ch09_12.htm
สัญลักษณ์แทน

เพื่อช่วยในการถอดรหัสคำแถลงการณ์ของมนุษย์:find . NOT ( *.txt OR *.pdf )
wisbucky

12

ด้วยการbashขยายแบบวงกลม (เปิดเครื่องด้วยshopt -s extglob) glob !(*.txt|*.pdf)จะทำงานได้ คุณสามารถส่งผ่าน glob นี้โดยตรงไปที่คำสั่งใด ๆ ที่จะเกิดการขัดแย้งไฟล์รวมถึง แต่ไม่ จำกัด lsเพียง


1
+1 แต่ถ้าคุณมีไดเรกทอรีย่อยเนื้อหาของพวกเขาก็จะถูกระบุเช่นกัน ใช้-dเพื่อหลีกเลี่ยงสิ่งนั้น:ls -d !(*.txt|*.pdf)
ตำนาน 2k

ขอขอบคุณที่ฉันถูกมองว่าสำหรับไวยากรณ์ที่จะยอมรับหลายไฟล์นี้จะเข้ากันได้ดีที่นี่stackoverflow.com/questions/216995/...
Freedo

6

ในzshกับextendedglob:

print -rl -- *~*.(txt|pdf)

หรือ

print -rl -- ^*.(txt|pdf)

หรือด้วยkshglob(ใช่นั่นคือ ksh globbing ไม่ใช่ "ทุบตีขยายแบบวงกลม"):

print -rl -- !(*.txt|*.pdf)

โปรดจำไว้ว่าสิ่งเหล่านั้นยังไม่รวมไฟล์จุด

ksh93 มีคุณสมบัติFIGNORE(mis):

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *


3

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

GNU (และ BSD บางแห่ง) findสนับสนุนเพรดิเคต-print0ที่บอกให้พิมพ์ชื่อไฟล์ที่ถูกยกเลิกด้วยอักขระNULซึ่งอักขระไม่ได้รับอนุญาตภายในชื่อไฟล์และรับประกันว่าจะไม่มีการชนกัน คำสั่งอื่น ๆ สามารถสั่งให้ใช้NULเป็นตัวคั่นอินพุต

สิ่งสำคัญที่สุดคือ GNU xargsซึ่งเรียกใช้คำสั่งที่คุณระบุและส่งผ่านรายการของไฟล์เป็นอาร์กิวเมนต์บรรทัดคำสั่ง คุณต้องการเรียกใช้xargs -r0ร่วมกับ find's -print0เช่น:

find . -type f ! \( -name \*.pdf -o -name \*.txt \) -print0 | xargs -r0 ls -ld

วิธีนี้จะพิมพ์รายชื่อไดเรกทอรีแบบยาวของไฟล์ pdfและtxtทั้งหมดรวมถึงที่มีช่องว่างหรืออักขระที่ไม่สามารถพิมพ์ได้ในชื่อ

คุณยังสามารถใช้กับ GNU ได้tarดังต่อไปนี้:

tar -zcf myarchive.tar.gz --null --files-from <(
  find . -type f ! -name \*.tar.gz -print0)

สิ่งนี้จะสร้างไฟล์ tar.gz ของไฟล์ทั้งหมดที่ชื่อไม่ลงท้ายด้วย. tar.gz

rsyncยอมรับไฟล์ที่คั่นด้วย null ด้วย-0พารามิเตอร์เช่นเดียวกับไฟล์อื่น ๆ แต่xargsเป็นกาวที่คุณมักจะใช้เพื่อจุดประสงค์ประเภทนี้ ทั้งที่หรือfind's -execคุณลักษณะ


tarตัวอย่างเช่นคำสั่งเป็นหนึ่งที่ดี แต่สำหรับจุดประสงค์ส่วนใหญ่-execนั้นเหมาะสมกว่า
Wildcard

1

หากคุณไม่มีไดเรกทอรีย่อย

ls !(*.pdf|*.txt)

ควรจะทำงาน!

แต่

ls -I "*.pdf" -I "*.txt"

เป็นวิธีทั่วไป


0

เป็นส่วนประกอบถ้าคุณใช้เชลล์ที่เข้ากันได้กับ bash คุณสามารถใช้ตัวแปร GLOBIGNORE เพื่อทำการเรซูเม่จากการจับคู่รูปแบบ จากคน:

   GLOBIGNORE
          A colon-separated list of patterns defining the set of filenames
          to be ignored by pathname expansion.  If a filename matched by a
          pathname  expansion  pattern also matches one of the patterns in
          GLOBIGNORE, it is removed from the list of matches.

ในกรณีของคุณโดยเฉพาะ:

sh$ (GLOBIGNORE='*.pdf:*.txt'; ls -d *)

โปรดทราบว่าฉันเรียกใช้คำสั่งนั้นเป็น sub-shell (โดยใช้วงเล็บ) เพื่อไม่ให้เปลี่ยนแปลงตัวแปรสภาพแวดล้อม GLOBIGNORE ของเชลล์แบบโต้ตอบของฉัน

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