J'essaie d'utiliser le résultat de ls
dans d'autres commandes (par exemple, echo, rsync):
all:
<Building, creating some .tgz files - removed for clarity>
FILES = $(Shell ls)
echo $(FILES)
Mais je reçois:
make
FILES = Makefile file1.tgz file2.tgz file3.tgz
make: FILES: No such file or directory
make: *** [all] Error 1
J'ai essayé d'utiliser echo $$FILES
, echo ${FILES}
Et echo $(FILES)
, sans succès.
Avec:
FILES = $(Shell ls)
mis en retrait sous all
comme ça, c'est une commande de construction. Donc cela élargit $(Shell ls)
, puis essaie d'exécuter la commande FILES ...
.
Si FILES
est supposé être une variable make
, ces variables doivent être affectées en dehors de la portion de recette, par exemple:
FILES = $(Shell ls)
all:
echo $(FILES)
Bien sûr, cela signifie que FILES
sera réglé sur "sortie de ls
" avant que n'exécute aucune des commandes. qui créent les fichiers .tgz. (Bien que notes Kaz la variable est ré-développée à chaque fois, elle inclura donc éventuellement les fichiers .tgz; certaines variantes de make ont FILES := ...
Pour éviter cela, par souci d'efficacité et/ou exactitude.1)
Si FILES
est supposé être une variable Shell, vous pouvez la définir, mais vous devez le faire dans Shell-ese, sans espaces, et cite:
all:
FILES="$(Shell ls)"
Cependant, chaque ligne est exécutée par un shell distinct. Cette variable ne survivra donc pas à la ligne suivante. Vous devez donc l'utiliser immédiatement:
FILES="$(Shell ls)"; echo $$FILES
Tout cela est un peu ridicule puisque le shell développera pour vous *
(Et d'autres expressions globales du shell), vous pouvez donc simplement:
echo *
comme votre commande Shell.
Enfin, en règle générale (ne s'applique pas vraiment à cet exemple): as esperanto note dans les commentaires, utiliser le résultat de ls
n’est pas totalement fiable (certains détails dépendent des noms de fichiers et parfois même la version de ls
; certaines versions de ls
tentent d’assainir la sortie dans certains cas). Ainsi, comme l0b et idélique remarque, si vous utilisez GNU vous pouvez utiliser $(wildcard)
et $(subst ...)
pour tout accomplir à l'intérieur de make
lui-même (en évitant les problèmes de "caractères étranges dans le nom de fichier"). (Dans sh
scripts, y compris la partie recette de makefiles, une autre méthode utiliser find ... -print0 | xargs -0
pour éviter de trébucher sur les blancs, les nouvelles lignes, les caractères de contrôle, etc.)
1Le GNU Complétez les remarques de la documentation en indiquant que POSIX a ajouté une affectation ::=
En 2012 . Je n'ai pas trouvé de lien de référence rapide vers un document POSIX pour cela. , je ne connais pas non plus à l'avance laquelle make
variantes supporte l'assignation ::=
, bien que GNU make le fasse aujourd'hui, avec la même signification que :=
, c’est-à-dire faire la tâche en ce moment avec expansion.
Notez que VAR := $(Shell command args...)
peut également être orthographié VAR != command args...
Dans plusieurs make
variantes, y compris toutes les variantes modernes GNU et BSD). Ces autres variantes n’ayant pas $(Shell)
, l’utilisation de VAR != command args...
Est supérieure car elle est plus courte et et fonctionne plus variantes.
En outre, en plus de la réponse de torek: une chose qui se démarque est que vous utilisez une affectation de macro évaluée paresseuse.
Si vous êtes sur GNU Make, utilisez l'affectation :=
Au lieu de =
. Cette assignation entraîne le développement immédiat du côté droit, puis son stockage dans la variable de gauche.
FILES := $(Shell ...) # expand now; FILES is now the result of $(Shell ...)
FILES = $(Shell ...) # expand later: FILES holds the syntax $(Shell ...)
Si vous utilisez l'affectation =
, Cela signifie que chaque occurrence de $(FILES)
développera la syntaxe $(Shell ...)
et invoquera ainsi la commande Shell. Cela ralentira votre travail, voire aura des conséquences surprenantes.