다음은 상위 디렉토리 및 확장자와 동일한 파일 이름이 포함된 경우 디렉토리 이름을 인쇄하는 단순화된 코드입니다 .md
.
FIND(){
find . -type d -exec sh -c '
for d do
[ -f "${d}/${d##*/}.md" ] && printf "%s\n" "$d"
done' find-sh {} +
}
FIND
${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'
나는 인용문에 몇 가지 문제가 있다고 확신합니다 SearchTerm
. 어떤 팁이 있나요?
시도했지만 FIND '\${d}/\${d##*/}.md'
출력이 없습니다
답변1
"${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'
# 작은따옴표로 시작하고 그 뒤에 큰따옴표가 옵니다.
더 명확해지기를 바랍니다.
답변2
호출하는 인라인 스크립트는 작은따옴표로 묶어야 합니다. 이것은 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
, 그렇지 않으면 테스트(true를 반환하는 무작동 유틸리티) testfunc
로 사용됩니다 .:
답변3
그냥 실행하는 대신 임의의 셸 코드를 실행할 수 있는 몇 가지 대안은 다음과 같습니다 [ -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'
를 사용하는 경우 glob 한정자 ( ) zsh
만 사용하여 임의의 셸 표현식으로 디렉터리를 추가로 한정할 수 있습니다 .e
/
e
print -rC1 ./**/*(ND/e['[ -f $REPLY/$REPLY:t.md ]'])
또는 다음 기능을 사용하세요.
has_md() [ -f $REPLY/$REPLY:t.md ]
print -rC1 ./**/*(ND/+has_md)
( N
for nullglob
, D
for 는 dotglob
숨겨진 파일과 디렉토리를 무시하지 않습니다)