2012-01-06 82 views
7

Tôi muốn sử dụng một vòng lặp để tìm thấy một số file và đổi tên họ:Làm thế nào để sử dụng một vòng lặp for trong thực hiện công thức

for i in `find [email protected] -name *_cu.*`;do mv $i "$(echo $i|sed s/_cu//)" 
    done 

này hoạt động trong vỏ. Nhưng làm thế nào tôi có thể làm điều này trong một công thức makefile?

+1

OFF- topic: nó sẽ là một ý tưởng tốt để trích dẫn ''* _cu. *'' trong lệnh find, khi bạn muốn mở rộng bằng cách tìm, không phải là shell đang gọi tìm. –

+0

Việc kích hoạt lệnh này sẽ không hoạt động ngay với '$ @' làm mục tiêu của bạn. – reinierpost

Trả lời

28

Có hai điều chính bạn cần phải biết khi đưa mảnh vỏ không tầm thường vào làm cho công thức nấu ăn: (! Dĩ nhiên)

  1. Commands trong công thức là thực hiện cùng một lúc, nơi lệnh có nghĩa là "dòng tiền tố trong công thức", có thể lây lan qua một số dòng makefile có dấu gạch chéo ngược.

    Vì vậy, đoạn vỏ của bạn phải được viết tất cả trên một dòng (có thể bị gạch chéo). Hơn nữa, nó được trình bày một cách hiệu quả với shell như một dòng đơn (các dòng mới bị gạch chéo không phải là các dòng mới đơn giản vì vậy không được sử dụng như các terminator của trình bao), vì vậy phải có cú pháp chính xác như vậy.

  2. Cả hai biến vỏ và làm cho biến được giới thiệu bởi dấu đô la ([email protected], $i), vì vậy bạn cần phải giấu biến shell của bạn từ làm bằng cách viết chúng như $$i. (Chính xác hơn, bất kỳ đô la đăng nhập bạn muốn được nhìn thấy bằng vỏ phải được thoát ra từ làm bằng cách viết nó như $$.)

Thông thường trong một kịch bản shell bạn sẽ viết lệnh riêng biệt trên dòng riêng biệt, nhưng ở đây bạn có hiệu quả chỉ nhận được một dòng duy nhất vì vậy phải tách các lệnh shell riêng lẻ bằng dấu chấm phẩy thay thế. Đưa tất cả lại với nhau ví dụ của bạn sản xuất:

foo: bar 
    for i in `find [email protected] -name *_cu.*`; do mv $$i "$$(echo $$i|sed s/_cu//)"; done 

hoặc tương đương:

foo: bar 
    for i in `find [email protected] -name *_cu.*`; do  \ 
     mv $$i "$$(echo $$i|sed s/_cu//)"; \ 
    done 

Chú ý rằng sau này, mặc dù nó đặt ra readably trên nhiều dòng, yêu cầu sử dụng cẩn thận cùng một dấu chấm phẩy để giữ vỏ hạnh phúc.

+0

Vì tò mò, tại sao bạn lại để nguyên '$ @'? Nó không có ý nghĩa đặc biệt trong Makefiles sao? Trong trình bao, nó mở rộng đến danh sách đối số tập lệnh ... – fge

+0

@fge: thực hiện chuyển lệnh cho trình bao như thông qua 'hệ thống()', vì vậy không có đối số tập lệnh shell và '$ @' của trình bao sẽ luôn luôn trống. OTOH làm cho '$ @' đề cập đến mục tiêu của quy tắc (ở đây _foo_), mà tôi giả định là những gì đã được dự định. –

+1

Vâng, tôi không chắc chắn, đoạn từ OP có vẻ thực sự là từ một kịch bản shell – fge

0

tôi thấy hữu ích này, cố gắng sử dụng cho vòng lặp để xây dựng nhiều file:

PROGRAMS = foo bar other 

.PHONY all 
all: $(PROGRAMS) 
$(PROGRAMS): 
    gcc -o [email protected] [email protected] 

Nó sẽ biên dịch foo.c, bar.c, other.c vào thanh foor thực thi khác

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