2015-03-09 3 views
1

В моем Makefile Я пытаюсь скопировать список файлов из location1 в location2, а затем в location2 в location3. Я получил следующее странное поведение:GNU make loop variable странное поведение

FILES_LIST=dir1/file1 dir2/file2 dir3/file3 ........ 

    mytarget: 
     for file in $(FILES_LIST) ; do \ 
      #this works 
      cp -vf location1/$$file location2/$(shell $$file##*/) ; \ 
      #this does not work 
      cp -vf location2/$(shell $$(file)##*/) location3/ ; \ 
     done 

Я использую "$ (оболочки $$ (файл) ## /)" раздеть "dir1 /" часть каждого элемента в FILES_LIST. Первый cp работает (от местоположения 1 до 2), однако отправка не выполняется, журнал сборки показывает, что «$ (shell $$ (file) ## /)» оценивается как пустое.

Я использую GNU Make 3.81

ответ

3

Проблема заключается в $$(file). Это не переменная оценка. Это командная замена. Вы имели в виду $${file} (ну не совсем, но мы доберемся до этого).

Там нет абсолютно нет оснований использовать $(shell) здесь все, как вы уже в контексте оболочки, когда эти строки запуска.

Не говоря уже о том, что звонки $(shell) не делают ничего, даже отдаленно, как то, что вы хотите (они не работают в нужное время для этого).

Вы хотите:

FILES_LIST=dir1/file1 dir2/file2 dir3/file3 ........ 

mytarget: 
    for file in $(FILES_LIST) ; do \ 
     #this works 
     cp -vf location1/$$file location2/$${file##*/} ; \ 
     #this does not work 
     cp -vf location2/$${file)##*/} location3/ ; \ 
    done 

$file Ваша переменная является переменной оболочки не делают один. Призыв к $(shell) не видит его. Вы эффективно используете $(shell $file##*/), который запускает команду $file##*/ через оболочку. Эта оболочка не имеет переменной $file, поэтому она становится комментарием ##*/, и все это ничего не возвращает. (На самом деле, я думаю, что комментарий может быть снят первым, но это ничего не меняет.)

+0

Вы прямо на месте сэр! Спасибо за подробное объяснение. "cp -vf location2/$$ {file ## * /} location3 /; \" работал для меня – user3894299

0

Используйте $ команду (notdir $ файла). notdir вычеркнет каталоги и вернет имя файла. Например, $ (notdir dir1/file.h) возвратит file.h

Ссылка на ссылку для получения более подробной информации: https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html

+0

проблема в том, что файл $$ оценивается пустым значением, если я помещаю его в круглые скобки: здесь отображается журнал: for заголовок в файле dir1/file1 dir2/file2 dir3/file3; do \ cp -vf/location2// location3; \ done cp: omitting directory '/ location2 /' – user3894299

+0

Поскольку файл определен в вашем файле make, но не в оболочке env, $$ (файл) становится $ (файлом) в оболочке и, следовательно, вычисляется как NULL. Используйте один $ вместо $$, т. Е. «Cp -vf location2/$ (shell $ (file) ## * /) location3 /" – Vivek

+0

'$ file' - это переменная оболочки, а не переменная make. –

Смежные вопросы