Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在bash中使用包含引号的字符串作为命令的参数,而无需额外转义 背景_Bash_Variables_Quoting - Fatal编程技术网

在bash中使用包含引号的字符串作为命令的参数,而无需额外转义 背景

在bash中使用包含引号的字符串作为命令的参数,而无需额外转义 背景,bash,variables,quoting,Bash,Variables,Quoting,我试图在find命令中排除git存储库的所有子模块。我知道我可以排除这样一个目录: find . -not -path './$submodule/*' 因此,我构建了一个命令,该命令生成并存储了大量这些语句: EXCLUDES=$(for submodule in $(git submodule status | awk '{print $2}'); do echo -n "-not -path './$submodule/*' "; done) 问题 但是当我运行find时$排除

我试图在find命令中排除git存储库的所有子模块。我知道我可以排除这样一个目录:

find . -not -path './$submodule/*'
因此,我构建了一个命令,该命令生成并存储了大量这些语句:

EXCLUDES=$(for submodule in $(git submodule status | awk '{print $2}'); do
    echo -n "-not -path './$submodule/*' ";
done)
问题 但是当我运行
find时$排除
,这不起作用。我怀疑这是因为我不理解的bash引用策略。例如,让我们假设(
#
标记输出):

树。
# .
# ├── 酒吧
# │   └── 巴兹斯卡拉酒店
# └── 福斯卡拉
集合x
EXCLUDES=“-not-path”。/bar/*”
找到-f类$不包括在内
#+查找-not-路径'\'./bar/*'\''.您注意到的“奇怪的东西”是因为bash只扩展
$EXCLUDES
一次,方法是替换存储在
EXCLUDES
中的值。它不会像在命令行上指定带引号的字符串那样,递归地处理
EXCLUDES
的内容以删除单引号。相反,bash会转义
$EXCLUDES
中的特殊字符,前提是您需要它们:

-not -path './bar/*'
变成

-not -path ''\''./bar/*'\'''
             ^^         ^^ escaped single quotes
           ^^             ^^ random empty strings I'm actually not sure about
               ^       ^ single quotes around the rest of your text.
因此,正如@Jean Françoisfare所说,如果你在
EXCLUDES=…
中去掉单引号,你就不会得到奇怪的东西

那么为什么第一个
find
没有按预期工作呢?由于bash将
$EXCLUDES
扩展为单个单词,即传递给
find
*的
argv
的单个元素,
find
希望其参数是单独的单词。因此,
find
无法实现您的期望

我所知道的做这类事情最可靠的方法是使用数组:

declare -a EXCLUDES    #make a new array
EXCLUDES+=("-not" "-path" './bar/*')
    # single-quotes       ^       ^ so we don't glob when creating the array
你可以重复+=行任意次数来排除你想要的。然后,要使用这些:

find . -type f "${EXCLUDES[@]}"
“${name[@]}”
表单使用所有标点符号将数组的每个元素扩展为一个单独的单词,但不会进一步扩展这些单词。因此,
/bar/*
将保持不变,而不是全球化。(如果确实要进行全局搜索,
find.-type f${EXCLUDES[@]}
(不带
)将展开数组的每个元素。)

编辑顺便说一下,要查看数组中的内容,请执行
set | grep EXCLUDES
。您将分别列出每个元素。您也可以执行
echo“${EXCLUDES[@]}”
,但我发现这对于调试不太有用,因为它不显示索引


*请参阅的“扩展”部分。“参数扩展”,即扩展以
$
开头的内容,无法更改命令行上的字数-除了
“$@”
“${name[@]}”

之外,您是否只是试图
grep
查找主repo中而不是子模块中的源文件?如果是这样,您可以使用
git grep
来实现这一点。您正在保护您的
子模块。简单引号中的变量。所以它没有被评估。不使用引号或双引号。@eddiem不,不使用grepping。这将是皮棉制作步骤的一部分。我需要一套特定的文件。@Jean-Françoisfare我不明白。为什么要对它进行评估(你是说全球化?)?在下面的示例中,将所有内容都更改为双引号并没有任何区别。@fresskoma您是否只关心repo中的文件(例如,与未老化的新文件相反)?如果是这样的话,您可以使用
git ls文件
。感谢您的详细回答:)@fresskoma很高兴为您提供帮助!顺便说一下,SMB SARSA FTW\o/:)
find . -type f "${EXCLUDES[@]}"