mv *.cache.{js,woff} sub_folder – работает как команда shell, но не внутри Makefile.

Вопрос или проблема

После сборки с помощью make я хочу переместить все файлы, которые оканчиваются на .cache.{js,woff}, в подпапку.

(cd $(PFROOT)/PVWR2/gwt/pdfwebviewer/; \
mkdir -p cache_files; \
mv *.cache.{js,woff} sub_folder)

Проблема в том, что при запуске make он, похоже, интерпретирует *.cache.{js,woff} как имя файла, а не что-то динамическое, и, конечно, нет файла с явным именем *.cache.{js,woff}.
Когда я просто перехожу в папку и перемещаю вручную через терминал с командой выше,
это работает без проблем.

Я понимаю, что это связано с глоббингом, но не знаю, как это исправить.

{...} — это синтаксис bash для расширения фигурных скобок, но make по умолчанию использует /bin/sh вместо bash.

Из info make, раздел 5.3.2:

Программа, используемая в качестве оболочки, берется из переменной SHELL. Если эта переменная не установлена в вашем makefile, программа /bin/sh используется как оболочка.

Если вы хотите использовать bash для разбора конструкций оболочки в вашем Makefile, вы можете добавить следующее в начало:

SHELL := /bin/bash

Ответ или решение

Когда вы работаете с Makefile и командой mv *.cache.{js,woff} sub_folder, возникает проблема в интерпретации этой команды на уровне командной оболочки. Вы столкнулись с особенностями работы Makefile, где появление ошибок может быть связано с неправильной интерпретацией конструкции оболочки (Command-shell construction).

Теория (Theory)

Для начала важно понимать, как функционирует оболочка в контексте Makefile. GNU Make по умолчанию использует /bin/sh как оболочку для команд. Эта оболочка в большинстве систем Unix-подобных не является bash и не поддерживает некоторые специфичные для bash конструкции, такие как brace expansion, используемую в команде *.cache.{js,woff}.

1. Глоббинга и brace expansion:
Глоббинг — это термин, обозначающий расширение шаблонов файлов в набор имен файлов. Конструкция *.cache.{js,woff} должна расшириться в два шаблона *.cache.js и *.cache.woff. Однако brace expansion является функцией bash, и если ваша команда интерпретируется в оболочке sh, это приведет к интерпретации всего выражения как одной строки, а не расширения в отдельные файлы.

Пример (Example)

При выполнении команды в shell взаимодействие происходит следующим образом:

# Открытие bash оболочки
$ cd /путь/к/вашей/директории
$ mv *.cache.{js,woff} sub_folder

Здесь команда выполняется bash, где расширение скобок происходит корректно: *.cache.js и *.cache.woff подставляются вместо конструкции {js,woff}. Команда mv затем перемещает все файлы, которые соответствуют этим паттернам, в каталог sub_folder.

Применение (Application)

Если вам необходимо обязать Make использовать bash, вы можете изменить оболочку, добавив соответствующую строчку в Makefile:

SHELL := /bin/bash

Это позволит использованию bash-расширений типа brace expansion. Вот как ваш Makefile должен выглядеть после изменения:

SHELL := /bin/bash

target_name:
    (cd $(PFROOT)/PVWR2/gwt/pdfwebviewer/; \
    mkdir -p cache_files; \
    mv *.cache.{js,woff} cache_files)

Однако, если смена оболочки нет возможности по ряду причин (например, система не поддерживает bash), вы можете изменить команду следующим образом, минуя brace expansion и нарушая совместимость со старыми POSIX-compliant конструкциями:

target_name:
    (cd $(PFROOT)/PVWR2/gwt/pdfwebviewer/; \
    mkdir -p cache_files; \
    mv *.cache.js *.cache.woff cache_files)

В случае сложных шаблонов, которые не могут быть обработаны однозначно простой заменой, можно использовать find и sed или другие утилиты командной строки для достижения цели в более POSIX-совместимой форме:

target_name:
    (cd $(PFROOT)/PVWR2/gwt/pdfwebviewer/; \
    mkdir -p cache_files; \
    find . -maxdepth 1 -name '*.cache.js' -exec mv {} cache_files \; \
    -name '*.cache.woff' -exec mv {} cache_files \;)

Здесь используется утилита find, которая проходит по файловой системе, находит файлы, соответствующие шаблону, и выполняет команду mv для каждого найденного файла.

Заключение

Проблема с вашей Makefile заключается в использовании конструкции, специфичной для bash, в оболочке sh. Понимание, какие функции поддерживаются текущей оболочкой, поможет избежать подобных ошибок. Смена оболочки, корректировка шаблонов или использование файловых утилит для обхода ограничений POSIX – это пути для успешного решения вашей проблемы.

Оцените материал
Добавить комментарий

Капча загружается...