ข้อผิดพลาดทางไวยากรณ์ใกล้กับโทเค็นที่ไม่คาดคิด `('


11

เมื่อฉันใช้โค้ดด้านล่างในเทอร์มินัล Ubuntu มันใช้งานได้ดี:

rm !(*.sh) -rf

แต่ถ้าฉันวางโค้ดบรรทัดเดียวกันในเชลล์สคริปต์ (clean.sh) และรันเชลล์สคริปต์จากเทอร์มินัลมันจะพ่นข้อผิดพลาด:

สคริปต์ clean.sh:

#!/bin/bash
rm !(*.sh) -rf

ข้อผิดพลาดที่ฉันได้รับ:

./clean.sh: line 2: syntax error near unexpected token `('
./clean.sh: line 2: `rm !(*.sh) -rf'

คุณช่วยได้ไหม


คำตอบ:


23

rm !(*.sh)เป็นextglobไวยากรณ์ที่หมายถึงลบไฟล์ทั้งหมดยกเว้นไฟล์ที่มี.shนามสกุล

ในbashอินสแตนซ์เชิงโต้ตอบของคุณตัวเลือกเชลล์extglobจะเปิดอยู่:

$ shopt extglob 
extglob         on

ตอนนี้เมื่อสคริปต์ของคุณทำงานใน subshell คุณต้องเปิดใช้งานextglobโดยเพิ่มสิ่งนี้ในตอนเริ่มต้นของสคริปต์:

shopt -s extglob

ดังนั้นสคริปต์ของคุณดูเหมือน:

#!/bin/bash
shopt -s extglob
rm -rf -- !(*.sh)

แก้ไข:

หากต้องการลบไฟล์ทั้งหมดยกเว้น.shนามสกุลไฟล์ให้ใช้GLOBIGNORE(เนื่องจากคุณไม่ต้องการเปิดใช้งานextglob):

#!/bin/bash
GLOBIGNORE='*.sh'
rm -rf *

ตัวอย่าง:

$ ls -1
barbar
bar.sh
egg
foo.sh
spam

$ GLOBIGNORE='*.sh'

$ rm *

$ ls -1
bar.sh
foo.sh

ฉันสามารถเปลี่ยนคำสั่งของฉันที่ทำแบบเดียวกันโดยไม่ต้องรันได้หรือไม่ shopt -s extglob?
Tal

@Tal ตรวจสอบการแก้ไขของฉัน ..
heemayl

1
ขอบคุณ :) (สแต็ค overflaw ทำให้ฉันเขียนอักขระ 15 ตัวในความคิดเห็น :( :( :()
Tal

แต่ที่นี่มีสองคำตอบที่ดี!
Tal

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับเพราะจริง ๆ แล้วตอบคำถามในขณะที่อีกคำตอบหนึ่งอธิบายวิธีแก้ปัญหา
Guntram Blohm สนับสนุนโมนิกา

4

ตกลงมันเป็นโพสต์ข้าม แต่ฉันต้องเขียนคำตอบ ;)

คุณสามารถใช้findแทน

find . -maxdepth 1 ! -name '*.sh' -exec rm -rf {} \;

2

คุณต้องเปิดextglob:

shopt -s extglob

1
@ Pilot6: man bashดู มันช่วยให้ขยายเหมือน!(...)กัน
choroba

ฉันสามารถเปลี่ยนคำสั่งของฉันที่ทำแบบเดียวกันโดยไม่ต้องรันได้หรือไม่ shopt -s extglob
Tal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.