ฉันจะลบไฟล์ที่มีหมายเลขในช่วงที่กำหนดได้อย่างไร


16

ฉันมีที่มีไฟล์บางคนที่มีหมายเลขลำดับเริ่มต้นด้วยfolderA a_000000สิ่งที่ฉันต้องการจะทำคือการลบไฟล์ที่เริ่มต้นจากจำนวนที่เฉพาะเจาะจง: สมมติว่าจนถึงสิ้นไฟล์ในนี้a_000750 folderAใครช่วยกรุณาแนะนำวิธีการใช้เชลล์สคริปต์?


ฉันสามารถสันนิษฐานได้ว่าชื่อไฟล์ทั้งหมดนั้นมีคำต่อท้าย 6 หลักหรือไม่
muru

ใช่พวกเขาคือ :) พวกเขาเริ่มจาก a_000000 จนถึงบางหมายเลข
ตาก

5
rm a_000[89]* a_0007[5-9]*?
Rinzwind

@Rinzwind คุณช่วยอธิบายคำสั่งนี้ได้ไหม?
ตาก

2
@ user1460166 a_000[89]*รวมทุกไฟล์ที่ขึ้นต้นด้วยa_0008หรือa_0009และa_0007[5-9]*รวมทุกไฟล์ที่ขึ้นต้นด้วยa_0007แล้วมีตัวเลขระหว่าง 5 ถึง 9 ตามด้วยอะไรก็ตาม
muru

คำตอบ:


35

สมมติว่าคุณรู้หรือคาดเดาจุดสิ้นสุดของช่วงคุณสามารถใช้การขยายรั้ง :

rm a_{000750..000850}

ด้านบนจะลบ 101 ไฟล์ระหว่าง a_000750 และ a_000850 รวม (และบ่นเกี่ยวกับชื่อไฟล์ที่อ้างถึงไฟล์ที่ไม่มีอยู่) หากคุณมีไฟล์มากเกินไปให้ใช้find:

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

นี่คือfindรายการไฟล์ทั้งหมดที่เข้าคู่a_*กัน รายการจะส่งผ่านไปยังวงที่ชื่อไฟล์แต่ละคนจะอ่านในตัวแปรwhile $fileจากนั้นใช้คุณสมบัติการจัดการสตริงของ bash หากส่วนที่เป็นตัวเลข (ค้นหาพิมพ์ไฟล์เป็น./fileดังนั้น${file#./a_}พิมพ์เฉพาะตัวเลข) 000750หรือมากกว่าไฟล์จะถูกลบ -vเป็นเพียงมีเพื่อให้คุณสามารถดูไฟล์ที่ถูกถอดออก

โปรดทราบว่าข้างต้นถือว่าเป็นชื่อไฟล์มีเหตุผล หากชื่อของคุณมีช่องว่างบรรทัดใหม่หรืออักขระแปลก ๆ ให้ใช้ชื่อนี้แทน:

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

ทำไมหลีกเลี่ยง[[?
muru

1
@muru ทำไมต้องใช้มัน? [[ไม่ลดความซับซ้อนของสิ่งต่าง ๆ ที่นี่[[ "${file#./a_}" > 000749 ]]เช่นไม่ทำให้สั้นลง ฉันไม่ชอบการใช้ไวยากรณ์ที่ไม่จำเป็นและสิ่งนี้จะทำงานในเชลล์ที่เรียบง่ายกว่าdashได้
terdon

เพราะ[[จัดการกับช่องว่างและความแปลกประหลาดได้ดีกว่า (ฉันไม่สนใจอะไรมาก>)
muru

1
@muru ใช่ แต่[ก็โอเคถ้าคุณพูดถึงตัวแปรที่ฉันมีอยู่ทำงานบนกระสุนได้มากกว่าและง่ายกว่า
terdon

หากคุณยืนยัน ไม่ใช่ปัญหาของฉัน.
muru

3

คุณสามารถทำสิ่งนี้:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

หรือ:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

วิธีแรกถือว่าคำนำหน้าคงที่ถอดออกแล้วตรวจสอบค่า

วิธีที่สองถือว่าคำต่อท้ายที่มีความยาวคงที่ (และคำนำหน้าคงที่ทั่วไป) และอาศัยความจริงนั้น และว่าในขณะที่201มาก่อน31ใน lexicographically 031ก็ไม่ได้ก่อน

ทดสอบechoคำสั่งนี้และเมื่อคุณแน่ใจว่ามันแสดงรายการไฟล์ที่ถูกต้องให้ใช้rmแทน


ไม่มีใครทำงาน: /
ตาก

@ user1460166 อานั่นอาจเป็นเพราะการจับคู่ regex ฉันจะอัปเดต
muru

ยังไม่ทำงาน btw, ไฟล์คือ. png :)
ตาก

@ user1460166 คุณสามารถพูดได้ว่ามันไม่ทำงานอย่างไร
muru

ฉันเปิด terminal, cd ไปที่โฟลเดอร์จากนั้นคัดลอกบรรทัดของคุณและวาง แต่ไฟล์จะไม่ถูกลบ
ตาก

0

โซลูชันเชลล์ POSIX

โซลูชั่นแรก terdon ของ อาศัยอยู่กับการขยายตัวรั้งซึ่งเป็นทรัพย์สินของbashและkshแต่ก็ไม่สามารถนำมาใช้ในมาตรฐาน/bin/shเปลือกซึ่งบน Ubuntu เป็น symlinked /bin/dashไป

ในกรณีที่คุณต้องพึ่งพา/bin/shการพกพาของสคริปต์โดยทั่วไปมีสองวิธีในการเข้าถึงสิ่งนี้ หนึ่งจะผ่านทางโค้ง เพียงและจากที่นั่นวิ่งcd folderA rm a_*อีกวิธีหนึ่งคือการใช้ C-style สำหรับลูปทางเลือกที่ใช้while <CONDITION>;do ...doneในภาษาเชลล์และจัดรูปแบบตัวเลขด้วยprintf:

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

echoแจ้งให้ทราบว่าการใช้งานที่นี่ฉัน แทนที่echo "$filename"ด้วยrm ./"$filename"หรือrm -- "$filename"เมื่อคุณพร้อมที่จะลบไฟล์ โปรดทราบด้วยว่าควรดำเนินการนี้เมื่อคุณcdแก้ไขลงในไดเรกทอรีที่ต้องการแล้ว

(ab) การใช้ awk

Awk เป็นภาษา C ที่ดีสามารถช่วยเราได้สองวิธี: (1) เราสามารถสร้างชื่อไฟล์ด้วย for-loop และจัดรูปแบบพวกมันผ่านsprintfฟังก์ชั่นและ (2) ลบไฟล์ที่กล่าวผ่านsystem()คำสั่งซึ่งจะผ่านชื่อไฟล์และrmคำสั่งที่สร้างขึ้นไปที่/bin/sh:

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

Perl

ดำเนินการต่อด้วยแนวคิดของวิธีการพกพาที่เรา "สร้าง" ชื่อไฟล์เราสามารถทำเช่นเดียวกันใน Perl:

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'

0

ง่ายเหมือน

rm partialfilename* -f

ในตัวอย่างของคุณมันคือ

rm a_00075* -f

1
ขออภัยที่จะพูด แต่นั่นไม่ใช่ช่วงเหล่านี้เป็นไฟล์ทั้งหมดที่เริ่มต้นด้วยa_00075...
Fabby

1
* เป็นไวด์การ์ด OP กำลังค้นหาคำตอบเกี่ยวกับวิธีลบ RANGE ของสิ่งต่าง ๆ ... เช่นถ้าคุณมีไฟล์ 1 ถึง 100 และต้องการลบ # 41 ถึง # 75
Joshua Besneatte
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.