ฉันต้องลบไฟล์ทั้งหมดที่มีนามสกุล. 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
แต่มันจะไม่ตรง.
หรือ..
ดังนั้นคุณจะไม่ส่งผลกระทบไดเรกทอรีแม่ว่าวิธีการ