Parenthesis bekerja di bash shell itu sendiri, tetapi tidak dalam skrip bash

11

Saya dapat menjalankan perintah ini dari prompt baris perintah saya:

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

Untuk secara rekursif menyalin semua konten folder kecuali untuk subdirektori yang disebutkan exclude-medalam direktori saat ini. Ini berfungsi persis seperti yang dimaksudkan. Namun, saya perlu ini bekerja dalam skrip bash yang saya tulis, di mana saya memilikinya:

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

Tetapi ketika saya menjalankan skrip:

bash my-script.sh

Saya mendapatkan ini:

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

Dan saya bingung mengapa itu bekerja dari command prompt, tetapi baris yang sama persis tidak bekerja dalam skrip bash.

nzifnab
sumber

Jawaban:

11

Itu karena sintaks yang Anda gunakan tergantung pada fitur bash tertentu yang tidak diaktifkan secara default untuk shell (skrip) non-interaktif. Anda dapat mengaktifkannya dengan menambahkan perintah yang relevan ke skrip Anda:

## Enable extended globbing features
shopt -s extglob

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

Ini adalah bagian yang relevan dari 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
terdon
sumber
Ini adalah kedua kalinya saya menemukan jawaban ini (ya, ingatan buruk). Kali ini mencoba menjalankan env > file1skrip dan mengeksekusi ./it, dan kemudian env > file2dan source it, dengan harapan bahwa saya akan menemukan perbedaan dalam envs, yang tidak terjadi. Bagaimana saya bisa secara program mencantumkan semua perbedaan antara dua shell (dalam hal ini interaktif vs non-interaktif)?
Enrico Maria De Angelis
2

Tambahkan baris ini di dekat bagian atas skrip Anda:

shopt -s extglob

!(...)adalah fitur pencocokan pola yang diperluas, Anda perlu extglobopsi untuk menggunakannya. Lihat shopt builtin untuk lebih jelasnya.

cuonglm
sumber