วิธีค้นหาไฟล์ทั้งหมดยกเว้นไฟล์ที่ระบุ


13

lsสามารถให้ผลเหมือน

[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# ls

CentOS-Base.repo CentOS-Debuginfo.repo CentOS-Media.repo CentOS-Vault.repo

แต่จริงๆแล้วผมหวังว่าจะเป็นเพียงแค่หาCentOS-Base.repo, CentOS-Debuginfo.repoและแต่ไม่CentOS-Vault.repo CentOS-Media.repoดังนั้นฉันจึงเรียกใช้คำสั่งนี้

ls [^\(Media\)]

แต่ฉันได้รับข้อมูลข้อผิดพลาดฉันควรทำอย่างไร?



@steeldriver ขอบคุณสำหรับการเชื่อมโยงของคุณที่เป็นประโยชน์มากสำหรับฉัน ..
yode

คุณอาจพิจารณาเปลี่ยนเชลล์ของคุณเป็นzshซึ่งมีสิ่งอำนวยความสะดวกการลบรูปแบบ
Basile Starynkevitch

คำตอบ:


10

ในกรณีที่ง่ายที่สุดคุณสามารถใช้คำสั่งต่อไปนี้ (ในกรณีที่คำย่อยที่ 1 คงที่CentOS):

ls CentOS-[BDV]*

  • [BDV] - คลาสของตัวอักษรเพื่อให้แน่ใจว่าคำย่อยที่สองเริ่มต้นด้วยหนึ่งในตัวละครที่ระบุ

หรือเหมือนกันกับการปฏิเสธ :

ls CentOS-[^M]*

หากคุณต้องการละเว้นชื่อไฟล์ทั้งหมดที่มีMตัวละครด้วยการใช้ GNU ของls(ตามปกติจะพบใน CentOS) ให้ใช้ตัวเลือก-I( --ignore):

ls -I '*M*'

-I, --ignore = PATTERN
ไม่แสดงรายการโดยนัยที่ตรงกับเชลล์PATTERN

วิธีละเว้นรายการด้วยMediaคำ:

ls -I '*Media*'

รูปแบบเหล่านั้นจะต้องผ่านคำต่อคำlsดังนั้นจะต้องยกมา (มิฉะนั้นเปลือกจะถือว่าพวกเขาเป็น globs เพื่อขยาย)


ทำไมเราไม่สามารถใช้ls *[^M]*
yode

ls CentOS-[^M]*ทำงาน แต่ls *[^M]*ทำไม่ได้ ..
yode

@ โหมดขึ้นอยู่กับสิ่งที่คุณต้องการละเว้น: การMปรากฏตัวของตัวละครหรือMediaคำ?
RomanPerekhrest

แต่ในกรณีของฉันเฉพาะไฟล์นั้นเท่านั้นที่มีรูปMคน
yode

3
รูปแบบมีความโลภ: * ตัวแรกตรงกับทุกอย่างยกเว้นตัวอักษรตัวสุดท้าย [^ M] จับคู่ตัวอักษรตัวสุดท้ายเพราะไม่มีตัวใดลงท้ายด้วย M และส่วนท้าย * ตรงกับสตริงว่าง ดังนั้นพวกเขาทั้งหมดตรงกัน และแม้ว่าบางสิ่งจะจบลงด้วย M มันจะยังคงตรงกันถ้ามีบางอย่างที่แตกต่างจาก M ที่อื่น: เช่นถ้าคุณมีไฟล์ชื่อ OOM ดาวดวงแรกจะตรงกับ O ตัวแรก [^ M] จะตรงกับ O ตัวที่สอง และจุดเริ่มต้นต่อท้ายจะตรงกับ M.
NickD

12

เปลือกหอยบางตัวมีการปฏิเสธแบบกลม ๆ

  • zsh -o extendedglob:

    ls -d -- ^*Media*
    ls -d -- *.repo~*Media* # ~ is "except" operator
    
  • ksh, zsh -o kshglob, bash -O extglob:

    ls -d -- !(*Media*)
    
  • bash:

    GLOBIGNORE='*Media*'
    ls -d -- *
    
  • ksh:

    FIGNORE='@(*Media|.)*'
    ls -d -- *
    

6

ทางเลือกหนึ่งคือใช้findกับ-not -name ธง find . -not -name CentOS-Media.repoกล่าวคือ หากคุณไม่ต้องการเรียกคืนโครงสร้างไดเรกทอรีให้เพิ่มการ-maxdepth 1ตั้งค่าสถานะ

อีกวิธีหนึ่งอาจเขียนต่อไปนี้ (ซึ่งมีความซับซ้อนมากขึ้น แต่ฉันลืมเกี่ยวกับการ-notตั้งค่าสถานะและโพสต์คำตอบนี้ แต่เดิมดังนั้นฉันจะไม่ลบส่วนนี้):

find . -print0 | grep --invert-match -z "CentOS-Media.repo$" | tr '\0' '\n'

คุณต้องบังคับfindให้แยกชื่อไฟล์ด้วยไบต์ที่ว่างเพื่อให้บรรทัดใหม่ในชื่อไฟล์ไม่แยกย่อย หวังว่าสนับสนุนชนิดของคั่นด้วยธงนี้grep -zคุณอาจต้องการเปลี่ยนกลับเป็นการแยกแบบทั่วไป (เช่น null byte -> บรรทัดใหม่) ด้วยtr '\0' '\n'


1
นอกจากนี้คุณยังสามารถรับชื่อไฟล์ที่คั่นด้วย null printf '%s\0' *ซึ่งไม่มีการเรียกคืนและไม่รวม dotfiles ตามค่าเริ่มต้น (แต่เชลล์บางตัวมีตัวเลือกสำหรับสิ่งนั้น) นอกจากนี้คุณยังไม่จำเป็นต้อง-Eสำหรับที่ regexp แต่จะจู้จี้จุกจิกคุณก็ควรจะทับขวา.หรือใส่ไว้ใน[]และคุณไม่ขึ้นอยู่กับGNUค้นหาและ grep
dave_thompson_085

4

วิธีที่ง่ายที่สุดคือใช้การค้นหา ทำ:

find . -maxdepth 1 -type f ! -name "CentOS-Media.repo"

ที่นี่ "f" หมายถึงค้นหาไฟล์ปกติเท่านั้น (ยกเว้น symlink ไปยังไฟล์ปกติด้วย GNU findให้ใช้-xtype fแทนเพื่อรวมไว้) หากคุณต้องการค้นหาไดเรกทอรีให้ส่งผ่าน "d" แทน

( -maxdepthในตอนแรกส่วนขยายของ GNU นั้นเป็นเรื่องปกติถ้าคุณfindไม่สนับสนุนคุณสามารถแทนที่-maxdepth 1ด้วยมาตรฐาน! -name . -prune)

ดูหน้าค้นหาคนสำหรับคุณสมบัติที่ยอดเยี่ยมกว่านี้

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