Por*_*ine 3 bash quoting function arguments
这是一个简化的代码,如果它包含与父目录和.md扩展名相同的文件名,则打印目录的名称。
FIND(){
find . -type d -exec sh -c '
for d do
[ -f "${d}/${d##*/}.md" ] && printf "%s\n" "$d"
done' find-sh {} +
}
FIND
Run Code Online (Sandbox Code Playgroud)
概括地说,我想将搜索词${d}/${d##*/}.md作为参数发送给FIND函数,但不幸的是,这不会输出任何内容:
FIND(){
local SearchTerm="${1}"
find . -type d -exec sh -c '
for d do
[ -f "${SearchTerm}" ] && printf "%s\n" "$d"
done' find-sh {} +
}
FIND '${d}/${d##*/}.md'
Run Code Online (Sandbox Code Playgroud)
我确信SearchTerm. 任何提示?
我试过了:FIND '\${d}/\${d##*/}.md'但没有输出
"${SearchTerm}"需要在 之外进行sh -c '推断,如下所示:
FIND(){
local SearchTerm="${1}"
find . -type d -exec sh -c '
for d do
[ -f "'"${SearchTerm}"'" ] && printf "%s\n" "$d"
done' find-sh {} +
}
FIND '${d}/${d##*/}.md'
Run Code Online (Sandbox Code Playgroud)
为了多解释一点,我们可以运行一个小测试:
SearchTerm='${d}/${d##*/}.md'
echo 'Before "$SearchTerm" After'
# output : Before "$SearchTerm" After
echo 'Before "'"$SearchTerm"'" After'
# output : Before "${d}/${d##*/}.md" After
Run Code Online (Sandbox Code Playgroud)
'Before "$SearchTerm" After' 是没有任何参数扩展的单个字符串,因为它全部在单引号中。
'Before "'"$SearchTerm"'" After' 实际上是三个字符串连接在一起:
'Before "' # 最后,它是一个双引号后跟一个单引号
"$SearchTerm" # 参数扩展发生在这里。
'" After' # 开头是单引号,后跟双引号
希望它更清楚。
您调用的内联脚本是单引号的(应该如此)。这意味着sh -cshell 将获得一个未展开的脚本"${SearchTerm}"。由于该 shell 没有SearchTerm变量,因此它的值将为空。
由于您用bash标记了您的问题,因此您可以传递导出函数的名称:
# Our find function.
# Takes the name of a test function that will be called
# with the pathname of a directory.
myfind () {
local thetest="$1"
# Run find, passing the name of the function into the in-line script.
find . -type d -exec bash -c '
testfunc=${1:-:}; shift
for dirpath do
"$testfunc" "$dirpath" && printf "%s\n" "$dirpath"
done' bash "$thetest" {} +
}
# Our test function.
test_md_file () {
[ -f "$1/${1##*/}.md" ]
}
export -f test_md_file
# Run the thing.
myfind test_md_file
Run Code Online (Sandbox Code Playgroud)
代码testfunc=${1:-:}中的 会分配$1给testfunc是否可用且不为空,否则,它将用作:测试(返回 true 的无操作实用程序)。