Dấu ngoặc đơn hoạt động trong bash shell, nhưng không phải trong bash script


11

Tôi có thể chạy lệnh này từ dấu nhắc dòng lệnh của mình:

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

Để sao chép đệ quy tất cả nội dung folder ngoại trừ thư mục con có tên exclude-mevào thư mục hiện tại. Điều này hoạt động chính xác như dự định. Tuy nhiên, tôi cần cái này để làm việc trong một kịch bản bash tôi đã viết, nơi tôi có cái này:

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

Nhưng khi tôi chạy tập lệnh:

bash my-script.sh

Tôi nhận được điều này:

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

Và tôi không biết tại sao nó hoạt động từ dấu nhắc lệnh, nhưng chính xác cùng một dòng không hoạt động trong tập lệnh bash.

Câu trả lời:


11

Đó là bởi vì cú pháp bạn đang sử dụng phụ thuộc vào một tính năng bash cụ thể không được kích hoạt theo mặc định cho các shell (script) không tương tác. Bạn có thể kích hoạt nó bằng cách thêm lệnh có liên quan vào tập lệnh của bạn:

## Enable extended globbing features
shopt -s extglob

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

Đây là phần có liên quan của 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

Đây là lần thứ hai tôi tìm thấy câu trả lời này (vâng, trí nhớ kém). Lần này cố gắng đưa chạy env > file1trong kịch bản và thực hiện ./it, và sau đó env > file2source it, với hy vọng rằng tôi đã tìm thấy một sự khác biệt trong envs, mà không phải là trường hợp. Làm thế nào tôi có thể liệt kê tất cả sự khác biệt giữa hai shell (trong trường hợp này là tương tác so với không tương tác)?
Enrico Maria De Angelis


2

Thêm dòng này gần đầu tập lệnh của bạn:

shopt -s extglob

!(...)là một tính năng khớp mẫu mở rộng, bạn cần extglobtùy chọn kích hoạt để sử dụng nó. Xem shopt dựng sẵn để biết thêm chi tiết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.