2012-01-06 12 views
7

Vorrei utilizzare un ciclo per trovare alcuni file e rinominarli:Come utilizzare un ciclo for nel make ricetta

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

Questo funziona nel guscio. Ma come posso farlo in una ricetta makefile?

+1

Off- argomento: sarebbe una buona idea citare ''* _cu. *'' all'interno del comando find, come vuoi espanso per find, non la shell che sta invocando find. –

+0

L'attivazione di questo comando non funzionerà correttamente con questo '$ @' come destinazione. – reinierpost

risposta

28

Ci sono due cose principali che dovete sapere quando mettere frammenti di conchiglie non banali nel fare le ricette: (! Ovviamente)

  1. comandi della ricetta vengono eseguiti uno alla volta, in cui comando significa "riga con prefisso di tabulazione nella ricetta", eventualmente distribuita su più righe di makefile con barre retroverse.

    Quindi il frammento della shell deve essere scritto tutto su una riga (possibilmente con il backslash). Inoltre è effettivamente presentato alla shell come una singola riga (le backlines backslashed non sono semplici newline quindi non vengono usate come terminatori di comando dalla shell), quindi deve essere sintatticamente corretta in quanto tale.

  2. Entrambe le variabili di shell e rendere variabili sono introdotti dal segno del dollaro ([email protected], $i), quindi è necessario per nascondere le variabili di shell da make scrivendoli come $$i. (Più precisamente, ogni segno del dollaro che si desidera essere visto dalla shell deve essere scappato dal make scrivendo come $$.)

Normalmente in uno script di shell si può scrivere comandi separati su righe diverse, ma qui in pratica si ottiene una sola riga, quindi è necessario separare i singoli comandi della shell con il punto e virgola. Mettendo insieme tutto questo per il vostro esempio produce:

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

o equivalentemente:

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

Si noti che questi ultimi, anche se è disposto essere letti su diverse linee, richiede lo stesso uso attento del punto e virgola per mantenere il guscio felice.

+0

Per curiosità, perché lasci '$ @' intatto? Non ha un significato speciale nei Makefile? Nella shell, si espande alla lista degli argomenti dello script ... – fge

+0

@fge: make passa il comando alla shell come se fosse tramite 'system()', quindi non ci sono argomenti di script della shell e '$ @' della shell essere sempre vuoto Il make di OTOH '$ @ 'si riferisce al target della regola (qui _foo_), che presumo fosse ciò che era inteso. –

+1

Beh, non sono sicuro, il frammento dell'OP sembra davvero essere uno script di shell – fge

0

ho trovato questo utile, cercando di utilizzare cicli for per costruire più file:

PROGRAMS = foo bar other 

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

Si compilerà foo.c, bar.c, other.c nella barra foor altri eseguibili