ฉันต้องลบไฟล์ทั้งหมดที่มีนามสกุล. gif ยกเว้นไฟล์เดียวที่มีชื่อว่า "filename.gif" วิธีที่ดีที่สุดในการทำสิ่งนี้ใน terminal คืออะไร?
RM คำสั่ง*.gifลบไฟล์ GIF filename.gifทั้งหมดรวมทั้งไฟล์
ฉันต้องลบไฟล์ทั้งหมดที่มีนามสกุล. gif ยกเว้นไฟล์เดียวที่มีชื่อว่า "filename.gif" วิธีที่ดีที่สุดในการทำสิ่งนี้ใน terminal คืออะไร?
RM คำสั่ง*.gifลบไฟล์ GIF filename.gifทั้งหมดรวมทั้งไฟล์
คำตอบ:
นี่เป็นวิธีง่ายๆที่คุณควรใช้:
mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif
ไม่มีอะไรพิเศษที่ตรงกับส่วนขยายนี้เพียงแค่ทำให้มันเพื่อให้ชื่อไฟล์ชั่วคราวไม่ได้จบใน.keep.gif
หากคุณไม่ต้องเปลี่ยนชื่อไฟล์ (และมีสถานการณ์การเขียนสคริปต์ที่มีความสำคัญ):
for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done
หรือคุณเขียนมันสั้นกว่านี้:
for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; doneคุณอาจต้องการใช้findแทน มีประสิทธิภาพมากคุณอาจพิจารณาว่าสามารถอ่านได้มากขึ้นและจัดการกับชื่อไฟล์แปลก ๆ ด้วยตัวละครเหมือน*ในตัว
find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -deleteฉันใช้-notโอเปอเรเตอร์เพื่อการอ่าน แต่ถ้าPOSIXมีความสำคัญ - ถ้าคุณไม่ได้ใช้ GNU find หรือถ้านี่เป็นสคริปต์ที่คุณต้องการแจกจ่ายต่อให้ผู้อื่นหรือทำงานในระบบที่หลากหลาย - คุณควร ใช้!โอเปอเรเตอร์แทน:
find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -deleteสิ่งหนึ่งที่มีประโยชน์เกี่ยวกับfindคือคุณสามารถปรับเปลี่ยนคำสั่งสำหรับ case-insensitivity ได้อย่างง่ายดายเพื่อให้สามารถค้นหาและลบไฟล์ที่มีนามสกุลเช่น.GIF:
find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -deleteโปรดทราบว่าผมเคยใช้-inameในสถานที่ของ-nameสำหรับรูปแบบการค้นหา*.gifแต่ฉันยังไม่ได้filename.gifใช้มัน สันนิษฐานว่าคุณรู้แน่ชัดว่าไฟล์ของคุณมีชื่อว่าอะไรและ-inameจะจับคู่กับการใช้อักษรตัวพิมพ์ใหญ่ไม่เพียง แต่ในส่วนขยายแต่ทุกที่ในชื่อไฟล์
โซลูชันทั้งหมดเหล่านี้จะลบไฟล์ที่อยู่ในไดเรกทอรีปัจจุบันทันที พวกเขาจะไม่ลบไฟล์ที่ไม่มีอยู่ในไดเรกทอรีปัจจุบันและพวกเขาจะไม่ลบไฟล์ที่อยู่ในไดเรกทอรีย่อยของไดเรกทอรีปัจจุบัน
หากคุณต้องการลบไฟล์ทุกที่ที่มีอยู่ภายในไดเรกทอรีปัจจุบัน (นั่นคือรวมถึงในไดเรกทอรีย่อยและในไดเรกทอรีย่อยของไดเรกทอรีย่อยเหล่านั้นและอื่น ๆ - ไฟล์ที่มีอยู่ในไดเรกทอรีปัจจุบันหรือลูกหลานของมัน) find โดยไม่ต้อง ใช้maxdepth -1:
find . -not -name 'filename.gif' -name '*.gif' -deleteระวังด้วย!
นอกจากนี้คุณยังสามารถตั้งค่าอื่น ๆ -maxdepthด้วย ตัวอย่างเช่นหากต้องการลบไฟล์ในไดเรกทอรีปัจจุบันและลูก ๆ และหลาน แต่ไม่ลึกกว่านี้:
find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -deleteเพียงให้แน่ใจว่าคุณไม่เคยใส่-deleteก่อนหน้าการแสดงออกอื่น คุณจะเห็นว่าฉันอยู่-deleteท้ายที่สุด ถ้าคุณวางไว้ที่จุดเริ่มต้นก็จะได้รับการประเมินครั้งแรกและทุกไฟล์ที่อยู่ภายใต้.(รวมถึงไฟล์ที่ไม่สิ้นสุดใน.gifและไฟล์ในลึกย่อยย่อย ... ไดเรกทอรีของ.) จะถูกลบ!
สำหรับข้อมูลเพิ่มเติมโปรดดูที่หน้าคู่มือสำหรับbashและshและสำหรับคำสั่งที่ใช้ในตัวอย่างเหล่านี้: mv, rm, [และ find(โดยเฉพาะ)
findซึ่งมีประโยชน์อย่างมาก
                    findจัดการกับชื่อไฟล์แปลก ๆ*ในนั้นดีกว่า for-loop อย่างไร สำหรับห่วงจัดการไฟล์ได้*ดีเพราะคุณใช้เครื่องหมายคำพูดคู่
                    หากคุณกำลังใช้bash(เชลล์เริ่มต้น) extglobตัวเลือกเชลล์จะช่วยให้คุณใช้ไวยากรณ์การจับคู่รูปแบบเพิ่มเติม หากต้องการเปิดใช้งานให้ใช้shoptคำสั่ง builtin:
shopt -s extglob(ฉันรวมบรรทัดนั้นไว้ใน.bashrcไฟล์ของฉัน)
เหนือสิ่งอื่นใดมันมอบสิทธิ์การเข้าถึง!()โอเปอเรเตอร์ซึ่งตรงกับลวดลายใด ๆ เพื่อจุดประสงค์ของคุณ:
rm !(filename).gifข้อมูลเพิ่มเติมมีอยู่ในman bash"การจับคู่รูปแบบ"
extglobต้องเปิดใช้งาน แต่ไม่มีอะไรเลวร้ายเกิดขึ้นถ้ามันถูกปิดการใช้งาน (ในกรณีนี้มันก็ไม่ทำงาน) และดูเหมือนว่าจะเปิดใช้งานตามค่าเริ่มต้นแม้ว่าฉันจะไม่มีshopt -s extglobไฟล์การกำหนดค่า (หรือระดับโลก) ก็ตาม หากมีคำอธิบายง่ายๆว่าทำไมมันถึงใช้ได้กับฉันนอกกรอบคุณอาจต้องการเพิ่มคำตอบนี้ หรือฉันอาจโพสต์คำถามใหม่
                    เปิดTerminalด้วยCtrl+ Alt+ Tและพิมพ์:
find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;ความแตกต่างระหว่าง-deleteและ-exec rm -vf {} \;คือกับตัวเลือกที่สองคุณจะสามารถดูไฟล์ที่ถูกลบเนื่องจากการ-vตั้งค่าสถานะ นั่นเป็นสิ่งที่ไม่สามารถทำได้ด้วย-deleteตัวเลือก ( -name -deleteจะพิมพ์ชื่อไฟล์ แต่rmกับ-vเผยถ้าแต่ละไฟล์ได้รับการประสบความสำเร็จลบ.)
มีGLOBIGNOREตัวแปร จากman bash:
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.
ดังนั้นวิธีง่ายๆคือตั้งค่าGLOBGINOREชื่อไฟล์ที่เป็นปัญหา:
$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png
ดังนั้นในกรณีของคุณ:
GLOBIGNORE=filename.gif; rm *.gifแน่นอนเนื่องจากGLOBIGNOREมีรูปแบบคุณสามารถใช้ทุกครั้งที่คุณต้องการยกเว้นรูปแบบ:
$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png
ข้อได้เปรียบ (?!) ของGLOBIGNOREคือการตั้งค่าจะแยก.และ..จากการจับคู่โดยอัตโนมัติและจะช่วยให้dotglob:
The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.
ดังนั้นวิธีที่ง่ายในการลบทุกไฟล์และโฟลเดอร์ในไดเรกทอรี:
GLOBIGNORE=.; rm -r **จะตรงกับชื่อไฟล์ที่เริ่มต้นด้วย.ตั้งแต่GLOBIGNOREเปิดใช้งานdotglobแต่มันจะไม่ตรง.หรือ..ดังนั้นคุณจะไม่ส่งผลกระทบไดเรกทอรีแม่ว่าวิธีการ