วงเล็บทำงานในเปลือก bash เอง แต่ไม่ใช่ใน bash script


11

ฉันสามารถเรียกใช้คำสั่งนี้จากพรอมต์บรรทัดคำสั่งของฉัน:

cp -r folder/!(exclude-me) ./

หากต้องการคัดลอกเนื้อหาทั้งหมดซ้ำfolder ยกเว้นไดเรกทอรีย่อยที่มีชื่อexclude-meลงในไดเรกทอรีปัจจุบัน งานนี้ตรงตามที่ตั้งใจไว้ อย่างไรก็ตามฉันต้องการสิ่งนี้เพื่อทำงานในสคริปต์ทุบตีที่ฉันเขียนซึ่งฉันมีสิ่งนี้:

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./
  rm -rf folder
fi

แต่เมื่อฉันเรียกใช้สคริปต์:

bash my-script.sh

ฉันได้รับสิ่งนี้:

my-script.sh: line 30: syntax error near unexpected token `('
my-script.sh: line 30: `  cp -r folder/!(exclude-me) ./'

และฉันก็ไม่รู้ว่าทำไมมันถึงทำงานได้จาก command prompt แต่บรรทัดเดียวกันที่แน่นอนไม่สามารถใช้งานได้ในสคริปต์ทุบตี

คำตอบ:


11

นั่นเป็นเพราะไวยากรณ์ที่คุณใช้ขึ้นอยู่กับคุณลักษณะทุบตีเฉพาะซึ่งไม่ได้เปิดใช้งานโดยค่าเริ่มต้นสำหรับเชลล์ที่ไม่ต้องมีการโต้ตอบ (สคริปต์) คุณสามารถเปิดใช้งานได้โดยเพิ่มคำสั่งที่เกี่ยวข้องลงในสคริปต์ของคุณ:

## Enable extended globbing features
shopt -s extglob

if [ -d "folder" ]; then
  cp -r folder/!(exclude-me) ./
  rm -rf folder
fi

นี่คือส่วนที่เกี่ยวข้องของman bash:

   If the extglob shell option is enabled using the shopt builtin, several
   extended  pattern  matching operators are recognized.  In the following
   description, a pattern-list is a list of one or more patterns separated
   by a |.  Composite patterns may be formed using one or more of the fol
   lowing sub-patterns:

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns

นี่เป็นครั้งที่สองที่ฉันพบคำตอบนี้ (ใช่หน่วยความจำไม่ดี) คราวนี้พยายามเรียกใช้env > file1สคริปต์และดำเนินการ./itแล้วenv > file2และsource itด้วยความหวังว่าฉันจะได้พบความแตกต่างในenvs ซึ่งไม่ใช่กรณี ฉันจะแสดงรายการความแตกต่างทั้งหมดระหว่างเชลล์สองโปรแกรมได้อย่างไร (ในกรณีนี้คือแบบโต้ตอบกับแบบไม่โต้ตอบ)
Enrico Maria De Angelis


2

เพิ่มบรรทัดนี้ใกล้ด้านบนของสคริปต์ของคุณ:

shopt -s extglob

!(...)เป็นคุณสมบัติการจับคู่รูปแบบเพิ่มเติมคุณต้องextglobเปิดใช้งานตัวเลือกเพื่อใช้งาน ดูรายละเอียดเพิ่มเติมที่shopt builtin

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