2016-09-01 14 views
5

kịch bản của tôi:logic OR trong shell script của tôi

#!/bin/bash 

for file in *.ats; 
do 
    if [[ ("${file}" = THx) || ("${file}" = THy)]] 
    then cp $file /home/milenko/procmt 
    fi 
done 

tập tin trong thư mục

262_V01_C00_R000_TEx_BL_128H.ats 
262_V01_C01_R000_TEy_BL_128H.ats 
262_V01_C02_R000_THx_BL_128H.ats 
262_V01_C03_R000_THy_BL_128H.ats 

Những gì tôi muốn là để sao chép các tập tin có chứa THX hoặc Thy, nhưng file không được sao chép. Tại sao?

+1

'cp * _TH [xy] _ *. Ats/home/milenk/procmt /'? Không có điểm để có một vòng lặp ở tất cả. –

Trả lời

4

Điều gì về cách sử dụng extglob cho hình cầu mở rộng? Bằng cách này bạn có thể sử dụng for bản thân để có được các phần mở rộng yêu cầu:

shopt -s extglob 
for file in *TH?(x|y)*.ats; do 
    # do things with "$file" ... 
done 

*TH?(x|y)*.ats mở rộng để các tập tin chứa <something> + TH + either x or y + <something> + .ats


Kịch bản của bạn không thành công vì bạn có một lỗi đánh máy trong đó:

if [[ ("${file}" = THx) || ("${file}" = THy)]] 
#          ^
#        missing space 

Điều này là tốt:

$ d="hi" 
$ [[ ($d == hi) || ($d == ha) ]] && echo "yes" 
yes 

Mặc dù ngoặc là không cần thiết:

$ [[ $d == hi || $d == ha ]] && echo "yes" 
yes 
+1

Trừ khi 'x' và' y' đại diện cho chuỗi multicharacter, '? (X | y)' tương đương với mẫu thông thường '[xy]'. – chepner

4

Bạn có thể sử dụng lớp nhân vật trong glob tức *TH[xy]* để kiểm tra xem $file chứa THx hoặc THy:

for file in *.ats; do 
    if [[ $file == *TH[xy]* ]]; then 
     cp "$file" /home/milenko/procmt 
    fi 
done 
5

Câu hỏi của bạn xác định "các tập tin có chứa THX hoặc Thy" ... nhưng mã của bạn xác định rằng tập tin tên THx hoặc THy.

+2

Không có tên tệp nào phù hợp với mẫu '* .ats' sẽ là' THy' và 'THx'. – Jdamian

9

Tôi nghĩ rằng bạn có thể tránh một vòng lặp hoàn toàn ở đây:

cp *TH[xy]*.ats /home/milenko/procmt 

Không cần để lặp qua kết quả và sau đó làm một so sánh riêng ; một glob duy nhất sẽ mở rộng đến danh sách các tệp mà bạn muốn.

Đã có một vài vấn đề với cách tiếp cận ban đầu của bạn:

  • Thứ nhất, bạn đã cố gắng để kiểm tra kết hợp chính xác, vì vậy tình trạng này sẽ không bao giờ là sự thật.
  • Ngoài ra, hãy quan tâm đến không gian: ]] là từ khóa trong lệnh ghép [[, do đó, từ khóa cần phải là một từ riêng biệt (tức là được bao quanh bởi khoảng trắng).
+2

Một caveat: vòng lặp là cần thiết nếu bạn đang mong đợi nhiều trận đấu hơn có thể phù hợp trên một dòng lệnh. Ngoài ra, trên một lưu ý cực kỳ phức tạp, ']' là một đối số cho lệnh * simple * '[', nhưng '[[...]]' là một lệnh * compound * sử dụng các từ khóa '[[' và ']] '. – chepner

+0

Cảm ơn, tôi đã cập nhật từ ngữ.Vì vậy, giới hạn chiều dài của vòng lặp 'for' lớn hơn giới hạn của lệnh' cp'? –

+1

Trong cả hai trường hợp, mẫu được chuyển đến bất kỳ chức năng thư viện nào mở rộng mẫu. Đối với một lệnh bên ngoài, bạn cần toàn bộ kết quả để xây dựng một danh sách đối số lớn để chuyển tới một cuộc gọi trong họ 'exec *'. Kích thước của danh sách đối số đó phải tuân theo giới hạn kích thước dành riêng cho hệ điều hành. Đối với một lệnh nội bộ, trình bao sẽ kiểm soát toàn bộ thời gian, vì vậy nó chỉ cần lấy một tệp tại một thời điểm từ kết quả để xử lý phần thân. – chepner

Các vấn đề liên quan