ฉันมีไดเรกทอรีที่มีดังต่อไปนี้:
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$varif-then0file -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.pdfx.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" และลบออกใช่ไหม หรือฉันเข้าใจผิด?