在bash中使用包含引号的字符串作为命令的参数,而无需额外转义 背景
我试图在find命令中排除git存储库的所有子模块。我知道我可以排除这样一个目录:在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 . -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[@]}"