查找 exec sh:Shell 变量未传递给 subshel​​l

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'但没有输出

Phi*_*ppe 5

"${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' # 开头是单引号,后跟双引号

希望它更清楚。


Kus*_*nda 2

您调用的内联脚本是单引号的(应该如此)。这意味着sh -cshell 将获得一个未展开的脚本"${SearchTerm}"。由于该 shell 没有SearchTerm变量,因此它的值将为空。

由于您用标记了您的问题,因此您可以传递导出函数的名称:

# 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 的无操作实用程序)。