ฉันมีไดเรกทอรีที่มีดังต่อไปนี้:
x.pdf
y.zip
z.mp3
a.pdf
ฉันต้องการที่จะลบไฟล์ทั้งหมดนอกเหนือจากและx.pdf
a.pdf
ฉันจะทำสิ่งนี้ได้อย่างไรจากเครื่องเทอร์มินัล ไม่มีไดเรกทอรีย่อยดังนั้นจึงไม่จำเป็นต้องเรียกซ้ำ
ฉันมีไดเรกทอรีที่มีดังต่อไปนี้:
x.pdf
y.zip
z.mp3
a.pdf
ฉันต้องการที่จะลบไฟล์ทั้งหมดนอกเหนือจากและx.pdf
a.pdf
ฉันจะทำสิ่งนี้ได้อย่างไรจากเครื่องเทอร์มินัล ไม่มีไดเรกทอรีย่อยดังนั้นจึงไม่จำเป็นต้องเรียกซ้ำ
คำตอบ:
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
.pdf
ชื่อไฟล์ตัวอย่างเช่นหากมีไดเรกทอรีที่เรียกว่าtemp
ในโฟลเดอร์บ้านของคุณ:
cd ~/temp
จากนั้นลบไฟล์:
find . -type f ! -iname "*.pdf" -delete
xyz.pdf
นี้จะลบไฟล์ทั้งหมดยกเว้น
คุณสามารถรวมสองคำสั่งนี้กับ:
find ~/temp -type f ! -iname "*.pdf" -delete
.
เป็นไดเรกทอรีปัจจุบัน !
หมายถึงการใช้ไฟล์ทั้งหมดยกเว้นไฟล์ที่มี.pdf
ในตอนท้าย -type f
เลือกไฟล์เท่านั้นไม่ใช่ไดเรกทอรี -delete
หมายถึงการลบ
!
-name
ก็-name
จะมีเฉพาะ.pdf
ในขณะที่-iname
จะรวมทั้งสอง.pdf
และ.PDF
หากต้องการลบเฉพาะในไดเรกทอรีปัจจุบันและไม่อยู่ในไดเรกทอรีย่อยให้เพิ่ม-maxdepth 1
:
find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
.
หมายถึงไดเรกทอรีปัจจุบัน !
หมายถึงใช้ไฟล์ทั้งหมดยกเว้นไฟล์ที่มี.pdf
ในตอนท้าย -delete
หมายถึงการลบ ตอนนี้ฉันชัดเจนไหม
-maxdepth 1
พารามิเตอร์ที่จะเริ่มต้นด้วย จากนั้นแนะนำให้ลบพารามิเตอร์ในกรณีที่ต้องการลบแบบเรียกซ้ำ
ด้วยการbash
ขยายเชลล์แบบขยายคุณสามารถลบไฟล์ใด ๆ ที่มีส่วนขยายนอกเหนือจากการ.pdf
ใช้งานได้
rm -- *.!(pdf)
ตามที่ระบุไว้โดย @pts --
อักขระจะระบุจุดสิ้นสุดของตัวเลือกคำสั่งใด ๆ ทำให้คำสั่งปลอดภัยในกรณีที่หายากของไฟล์ที่ชื่อขึ้นต้นด้วย-
อักขระ
หากคุณต้องการลบไฟล์ที่ไม่มีนามสกุลใด ๆ รวมถึงไฟล์ที่มีนามสกุลอื่นนอกจาก.pdf
ที่ระบุไว้โดย @DennisWilliams คุณสามารถใช้
rm -- !(*.pdf)
การขยายแบบวงกลมควรเปิดใช้งานโดยค่าเริ่มต้น แต่หากไม่ใช่คุณสามารถทำได้
shopt -s extglob
โดยเฉพาะอย่างยิ่งหากคุณต้องการใช้สิ่งนี้ภายในสคริปต์สิ่งสำคัญที่ควรทราบคือหากนิพจน์ไม่ตรงกับสิ่งใด (เช่นถ้าไม่มีไฟล์ที่ไม่ใช่ไฟล์ pdf ในไดเรกทอรี) จากนั้นค่าเริ่มต้น glob จะถูกส่งไปยังrm
คำสั่งทำให้เกิดข้อผิดพลาดเช่น
rm: cannot remove `*.!(pdf)': No such file or directory
คุณสามารถปรับเปลี่ยนพฤติกรรมเริ่มต้นนี้ได้โดยใช้nullglob
ตัวเลือกเชลล์อย่างไรก็ตามมีปัญหาของตัวเอง สำหรับการสนทนาที่ละเอียดยิ่งขึ้นดูที่NullGlob - Wiki ของ Greg
rm *~*.pdf
!(*.py)
. นอกจากนี้สมมุติว่าถ้า OP ต้องการไฟล์ ".pdf" ที่เหลืออยู่เท่านั้นไฟล์ที่ไม่มีนามสกุลก็ควรจะถูกลบและจะไม่ถูกละเว้นด้วย
$ cd <the directory you want>
$ gvfs-trash !(*.pdf)
หรือผ่านmv
คำสั่ง (แต่ด้วยวิธีนี้คุณจะไม่สามารถกู้คืนได้จากถังขยะเนื่องจากไม่ได้บันทึกข้อมูล. trashinfo ดังนั้นหมายความว่าคุณย้ายไฟล์ไปยังปลายทางที่มีดังต่อไปนี้)
mv !(*.pdf) ~/.local/share/Trash/files
rm
วิธีนี้จะมีความปลอดภัยมากกว่าโดยตรงโดยใช้
วิธีที่ง่ายที่สุด: สร้างไดเรกทอรีใหม่ที่ใดที่หนึ่ง (ถ้าคุณเพียงลบในไดเรกทอรีเดียวไม่ซ้ำมันอาจเป็นไดเรกทอรีย่อย); ย้ายไฟล์. pdf ทั้งหมดไปที่นั่น ลบทุกอย่างอื่น ย้ายไฟล์ PDF กลับ ลบไดเรกทอรีกลาง
รวดเร็วง่ายคุณสามารถเห็นสิ่งที่คุณกำลังทำ ตรวจสอบให้แน่ใจว่าไดเรกทอรีระดับกลางอยู่ในอุปกรณ์เดียวกับไดเรกทอรีที่คุณกำลังล้างข้อมูลเพื่อให้การเคลื่อนไหวเปลี่ยนชื่อไม่ใช่คัดลอก!
ใช้ GLOBIGNORE ของ bash:
GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE
จากหน้าคนของทุบตี:
GLOBIGNORE: รายการรูปแบบที่คั่นด้วยโคลอนจะกำหนดชุด ของชื่อไฟล์ที่จะละเว้นโดยการขยายชื่อพา ธ
การทดสอบอย่างรวดเร็ว:
mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *
เอาท์พุท:
y.zip z.mp3
นี่คือวิธีการที่ผมชอบเพราะมันช่วยให้ฉันต้องระวังให้มาก: เขียนวิธีที่จะแสดงเพียงไฟล์ที่ฉันต้องการจะลบแล้วส่งพวกเขาไปใช้rm
xargs
ตัวอย่างเช่น:
ls
แสดงให้ฉันเห็นทุกอย่างls | grep pdf
แสดงไฟล์ที่ฉันต้องการเก็บไว้ อืมมมls | grep -v pdf
แสดงสิ่งที่ตรงกันข้าม: ทั้งหมดยกเว้นสิ่งที่ฉันต้องการเก็บไว้ พูดอีกอย่างคือมันแสดงรายการสิ่งที่ฉันต้องการลบ ฉันสามารถยืนยันสิ่งนี้ก่อนที่จะทำอะไรอันตรายls | grep -v pdf | xargs rm
ส่งรายการนั้นไปยังrm
การลบอย่างแน่นอนอย่างที่ฉันพูดฉันชอบเรื่องนี้เป็นหลักเพื่อความปลอดภัย: ไม่มีอุบัติเหตุrm *
สำหรับฉัน ข้อดีสองประการอื่น ๆ :
ls
หรือfind
เพื่อรับรายการเริ่มต้นตามที่คุณต้องการ คุณสามารถใช้สิ่งอื่นที่คุณชอบในกระบวนการ จำกัด รายการนั้น - grep
บางรายการawk
หรืออะไรก็ตาม หากคุณต้องการลบเฉพาะไฟล์ที่ชื่อมีสีคุณสามารถสร้างมันขึ้นมาได้ด้วยวิธีเดียวกันfind
ในการค้นหาและrm
ลบออกซึ่งต่างจากการจำได้ว่าfind
ยอมรับการ-delete
ตั้งค่าสถานะ และถ้าคุณทำเช่นนี้อีกครั้งคุณสามารถเขียนทางเลือก อาจจะแทนrm
คุณสามารถสร้างtrash
คำสั่งที่จะย้ายไฟล์ไปที่ถังขยะ (ให้ "ยกเลิกการลบ") rm
และท่อที่แทน คุณไม่จำเป็นต้องได้find
รับการสนับสนุนตัวเลือกนั้นคุณเพียงไปที่มันดูความคิดเห็นโดย @pabouk สำหรับวิธีแก้ไขสิ่งนี้เพื่อจัดการกับกรณีขอบบางอย่างเช่นตัวแบ่งบรรทัดในชื่อไฟล์ชื่อไฟล์เช่นmy_pdfs.zip
ฯลฯ
pdf
ชื่อใด ๆ --- b)มันจะลบไฟล์ PDF หากตัวอักษรใด ๆ ในคำต่อท้ายเป็นตัวพิมพ์ใหญ่ --- c)ls
มันไม่ได้เป็นความคิดที่ดีที่จะใช้การส่งออกของ มันจะไม่ทำงานกับชื่อไฟล์ที่มีการขึ้นบรรทัดใหม่ การใช้งานบางส่วนของแทนที่ตัวอักษรพิเศษเช่นโดยแท็บls
?
--- find -maxdepth 1 -print0
มันจะดีกว่าที่จะใช้: (ไม่สั้นอย่างที่ls
:) ----- เพื่อแก้ปัญหา a) และ b) ใช้grep -vi '\.pdf$'
--- โซลูชันที่สมบูรณ์ (แต่ GNU เท่านั้น):find -maxdepth 1 -print0 | grep -viz '\.pdf$' | xargs -0 rm
| head -20
อย่างน้อยสามารถดูได้ว่ามันดูถูกต้องหรือไม่ในขณะที่ถ้าคุณเพิ่งrm my_pattern
คุณจะไม่มีโอกาสพบข้อผิดพลาดครั้งใหญ่
find . -type f ! -name "*.pdf"
เพื่อพิมพ์ไปยังคอนโซลหรือไปป์ที่น้อยกว่าหรือไฟล์ [จากนั้นไปป์ที่ xargs ถึง rm หากต้องการเช่นความคิดเห็นของ pabouk (ด้วย -print0 | ... -0 สำหรับชื่อไฟล์แปลก)]
ฉันมักจะแก้ปัญหาดังกล่าวจากล่าม Python แบบโต้ตอบ:
mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
... if not f.endswith('.pdf'):
... os.remove(f)
มันอาจจะยาวกว่าหนึ่งซับด้วยfind
หรือxargs
แต่ก็ยืดหยุ่นอย่างมากและฉันรู้ว่ามันทำอะไรโดยไม่ต้องค้นคว้าก่อน
for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
[os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
คำตอบที่ดีกว่า (เทียบกับคำตอบก่อนหน้าของฉัน) กับคำถามนี้จะใช้file
คำสั่งที่มีประสิทธิภาพ
$ file -i abc.pdf
abc: application/pdf; charset=binary
ตอนนี้ปัญหาของคุณ:
cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done
การปฏิบัติงานของคำสั่งให้ไฟล์ในไดเรกทอรีปัจจุบันในรูปแบบของตัวแปรfor
คำสั่งแสดงชื่อของไฟล์ PDF โดยการออกจากสถานะของจากคำสั่งก็จะให้ออกจากสถานะของเท่านั้นหากพบไฟล์ PDF$var
if-then
0
file -i "$var" | grep -q 'application/pdf\;'
0
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
คำเตือน! ดีกว่าลองก่อน
ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
-i
กับgrep
การจับคู่แบบตรงตามตัวพิมพ์ใหญ่ - เล็ก
rm -i -- !(*@(a|x).pdf)
อ่านเป็นลบไฟล์ทั้งหมดที่ไม่ได้หรือa.pdf
x.pdf
นี้ทำงานโดยการใช้ 2 globs ขยายด้านนอก!()
เพื่อแก้ glob อยู่ที่ตัวเองต้องการให้ glob จะต้องตรงกับหนึ่งหรือมากกว่าa
หรือx
รูปแบบก่อนที่จะ.pdf
ต่อท้าย ดูglob # extglob
$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3
$ echo -- !(a.pdf)
-- x.pdf y.zip z.mp3
$ echo -- !(x.pdf)
-- a.pdf y.zip z.mp3
$ echo -- !(a.pdf|x.pdf)
-- y.zip z.mp3
$ echo -- !(@(a|x).pdf) # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.zip z.mp3
$ echo -- !(*@(a|x).pdf) # but this doesn't
-- y.zip z.mp3
$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.zip z.mp3
$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'
พริตตี้ POSIX มากและเข้ากันได้กับบอร์นเชลล์สไตล์ ( ksh
, bash
, dash
) เหมาะอย่างยิ่งสำหรับสคริปต์แบบพกพาและเมื่อคุณไม่สามารถใช้bash
เชลล์แบบขยายได้
$ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'
หรือทำความสะอาดเล็กน้อย:
$ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'
python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
ระวังสิ่งที่คุณกำลังลบอยู่!
วิธีที่ปลอดภัยในการทดสอบก่อนที่จะพยายามลบคือการทดสอบก่อนด้วยls
เนื่องจากพฤติกรรมที่ไม่ถูกตรวจจับบางอย่างสามารถลบไฟล์ที่ไม่ต้องการได้ และคุณสามารถทำได้โดยตรงนอกไดเรกทอรี ls
คล้ายกับrm
ดังนั้น:
ls sub/path/to/files/!(*.pdf)
รายการนี้จะ
y.zip
z.mp3
และตอนนี้คุณสามารถเห็นสิ่งที่คุณกำลังลบและสามารถลบได้อย่างปลอดภัย:
rm sub/path/to/files/!(*.pdf)
และนั่นคือมัน Yo สามารถใช้สัญลักษณ์แทน*
เพื่อเลือกเพิ่มเติมเช่นการเก็บเอกสารหลักสูตรการเขียนโปรแกรมเท่านั้น:
rm sub/path/to/files/!(*programming*)
.
หมายถึง "และ"?!
หมายถึง "ยกเว้น"-name
หมายความว่าคุณต้องการยกเว้นด้วยพารามิเตอร์ชื่อจากนั้น-delete
จะมีการดำเนินการเมื่อค้นหาหรือไม่ ดังนั้นจึงมองหาทุกอย่างยกเว้น "* .pdf" และลบออกใช่ไหม หรือฉันเข้าใจผิด?