Как я могу передать сложный файловый глобус в подоболочку? - PullRequest
2 голосов
/ 24 июня 2019

Я пытаюсь использовать git ls-files с шаблонами файлов, чтобы получить отфильтрованный список отслеживаемых файлов. (я знаю, что мог бы сделать следующее с помощью grep и др., Но мне любопытно, почему это не работает)

#!/usr/bin/env bash

GIT_ROOT=$(git rev-parse --show-toplevel)
# only include stuff in src and include
SRC_PATTERNS="{include,src}/**/*.{hpp,cpp,tpp,h,c}"

# @brief    Get list of files in git index with names relative to root
# @param    $1  Any of the constraints git-ls-files knows (e.g. --cached)
function git_sources()
{
    FILE_STRING=$(git -C $GIT_ROOT ls-files --full-name $1 $SRC_PATTERNS)
    echo "$FILE_STRING"
}

Глобус, который я использую, работает при вызове команды git ls-files из командной строки

git -C $GIT_ROOT ls-files --full-name --cached {include,src}/**/*.{hpp,cpp,tpp,h,c}

Но не при вызове команды git_sources после поиска сценария.

Вопрос: Как правильно заключить в кавычки шаблон глоба, чтобы он передавался подкоманде, как если бы он вызывался непосредственно из командной строки?

1 Ответ

4 голосов
/ 24 июня 2019

Это, вероятно, из-за того, как shell расширяет строку глобуса, хранящуюся в переменной.Независимо от того, какие цитаты вы используете, оболочка не расширяет команду, содержащую строку glob, в результирующие файлы, к которым вы можете применить фильтр.

Оболочка выполнит глобализацию после раскрытия переменной без кавычек, но поскольку расширение скобки выполняется до раскрытия переменной (ссылка Расширения оболочки ), глобус не найдет подходящих файлов и оболочкиоставляет буквенную глобальную строку

Когда вы запускаете

git -C $GIT_ROOT ls-files --full-name --cached {include,src}/**/*.{hpp,cpp,tpp,h,c}

Оболочка расширяет глобальную строку после части --cached до file1..fileN в зависимости от того, сколько файлов соответствует вашему определению глобуса,то есть как

git -C $GIT_ROOT ls-files --full-name --cached file1 file2 ... fileN

Но то же самое происходит , а не , когда ваша строка глобуса заключена в кавычки (раскрыта из переменной), она раскрывается как

git -C $GIT_ROOT ls-files --full-name --cached '{include,src}/**/*.{hpp,cpp,tpp,h,c}'

, чтоваша строка глобуса остается нерасширенной.

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

SRC_PATTERNS=({include,src}/**/*.{hpp,cpp,tpp,h,c})

Теперь в массиве уже хранится список файлов, соответствующих вашему определению глобуса, и нам просто нужно передать его команде, как показано ниже.${arr[@]} - это расширение массива в кавычках, чтобы гарантировать, что символы мета-оболочки в именах файлов не приводят к разделению имен

git -C "${GIT_ROOT}" ls-files --full-name --cached "${SRC_PATTERNS[@]}"

Всегда используйте кавычки для расширения переменных оболочки (если вы не видите хорошийпричина не, что в большинстве случаев нет) и используйте имена переменных в нижнем регистре без _ в имени файла.

...