Find exec sh: переменная оболочки не передается в подоболочку

Если вам разрешено создавать виртуальные машины в качестве непривилегированного пользователя, вы можете настроить среду с достаточным пространством подкачки.

3
22.01.2020, 12:07
3 ответа

Сценарий строки -, который вы вызываете, является одинарным -цитируемым (, как и должно быть ). Это означает, что оболочка sh -cполучит скрипт, в котором "${SearchTerm}"не раскрыт. Поскольку в этой оболочке нет переменной 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

testfunc=${1:-:}в коде будет назначать $1на testfunc, если он доступен и не пуст, в противном случае он будет использовать :в качестве теста (утилита no -op, которая возвращает true ).

2
27.01.2020, 21:10

"${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'

Чтобы объяснить немного больше, мы можем запустить небольшой тест:

SearchTerm='${d}/${d##*/}.md'
echo 'Before "$SearchTerm" After'
# output : Before "$SearchTerm" After
echo 'Before "'"$SearchTerm"'" After'
# output : Before "${d}/${d##*/}.md" After

'Before "$SearchTerm" After'— это одна строка без расширения параметров, потому что все это в одинарных кавычках.

'Before "'"$SearchTerm"'" After'на самом деле три струны, соединенные вместе:

'Before "'#в конце двойная кавычка, за которой следует одинарная кавычка

"$SearchTerm"#здесь происходит расширение параметра.

'" After'#в начале,это одинарная кавычка, за которой следует двойная кавычка

Надеюсь, стало понятнее.

5
27.01.2020, 21:10

Некоторые альтернативные подходы для запуска произвольного шелл-кода вместо простого[ -f "$d/${d##*/}.md" ]:

Передайте шелл-код в качестве первого аргумента и используйте evalдля его интерпретации:

FIND(){
    find. -type d -exec sh -c '
        code=$1; shift
        for d do
            eval "$code" && printf "%s\n" "$d"
        done' find-sh "$1" {} +
}
FIND '[ -f "$d/${d##*/}.doc" ]'

То же самое с переменной окружения

FIND(){
    CODE=$1 find. -type d -exec sh -c '
        for d do
            eval "$CODE" && printf "%s\n" "$d"
        done' find-sh "$1" {} +
}
FIND 'base=${d##*/}; [ -f "$d/$base.md" ] && [ -f "$d/$base.doc" ]'

Если шелл-код для интерпретации всегда будет[ -f "something" ]:

FIND(){
    FILE_TEST=$1 find. -type d -exec sh -c '
        for d do
            eval "[ -f \"$FILE_TEST\" ]" && printf "%s\n" "$d"
        done' find-sh "$1" {} +
}
FIND '$d/${d##*/}.doc'

Обратите внимание, что при использовании zshвы можете просто использовать его квалификатор eglob для дальнейшего уточнения каталогов(/)с помощью произвольной оболочки expression:

print -rC1./**/*(ND/e['[ -f $REPLY/$REPLY:t.md ]'])

Или с функцией:

has_md() [ -f $REPLY/$REPLY:t.md ]
print -rC1./**/*(ND/+has_md)

(Nдля nullglob, Dдля dotglob, чтобы не игнорировать скрытые файлы и каталоги)

2
27.01.2020, 21:10

Теги

Похожие вопросы