Если вам разрешено создавать виртуальные машины в качестве непривилегированного пользователя, вы можете настроить среду с достаточным пространством подкачки.
Сценарий строки -, который вы вызываете, является одинарным -цитируемым (, как и должно быть ). Это означает, что оболочка sh -c
получит скрипт, в котором "${SearchTerm}"
не раскрыт. Поскольку в этой оболочке нет переменной 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
testfunc=${1:-:}
в коде будет назначать $1
на testfunc
, если он доступен и не пуст, в противном случае он будет использовать :
в качестве теста (утилита no -op, которая возвращает true ).
"${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'
#в начале,это одинарная кавычка, за которой следует двойная кавычка
Надеюсь, стало понятнее.
Некоторые альтернативные подходы для запуска произвольного шелл-кода вместо простого[ -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
вы можете просто использовать его квалификатор e
glob для дальнейшего уточнения каталогов(/
)с помощью произвольной оболочки e
xpression:
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
, чтобы не игнорировать скрытые файлы и каталоги)