glob 변수는 큰따옴표로 묶어야 합니다.

glob 변수는 큰따옴표로 묶어야 합니다.

이 링크:따옴표 안의 와일드카드 문자 제 경우에는 문제가 해결되지 않았습니다.
"a.sh" 파일에는 다음이 포함됩니다.

file="path with wildcard*"

"b.sh" 파일에는 다음이 포함됩니다.

. a.sh
[ -f "$file" ] && echo ok

왜냐하면

"$file"

와일드카드 문자를 확장하지 않지만 대신

$file

와일드카드를 확장했지만 오류 발생: "이진 연산자가 필요합니다."

이 딜레마를 어떻게 해결합니까? 큰따옴표에서 와일드카드 문자를 추출할 수 없습니다.

편집:
와일드카드를 통해 단일 일치를 달성하고 싶습니다. 일치하는 항목이 더 있으면 조건은 false를 반환해야 하며 어쨌든 오류가 반환되어야 합니다.

답변1

에 보관하고 싶다면대량으로glob 패턴 확장으로 생성된 파일 목록은 다음과 같은 변수에 저장됩니다 bash.

pattern='path with wildcard*'

IFS= # disable splitting

shopt -s nullglob # make globs that don't match any file expand to nothing
                  # instead of the unexpanded pattern.

files=($pattern) # here using split+glob (unquoted expansion in list context)
                 # with the splitting disabled above.

또는 스칼라 변수를 $files사용하지 않고 배열을 직접 할당합니다 .$pattern

shopt -s nullglob # make globs that don't match any file expand to nothing
                  # instead of the unexpanded pattern.

files=('path with wildcard'*)

그런 다음 다음을 사용하여 목록이 비어 있는지 테스트할 수 있습니다.

if [ "${#files[@]}" -gt 0 ]; then
  echo it did find some files
fi

이러한 파일 중 하나 이상이 일반 파일인지 확인하려면(심볼릭 링크 확인 후) 다음을 수행할 수 있습니다.

has_regular_files() {
  local file
  for file do
    [ -f "$file" ] && return
  done
  false
}

if has_regular_files "${files[@]}"; then
  echo there was at least one regular file in the list
fi

하나의 파일에만 일치하고 해당 파일이 일반 파일인지 확인하려면 다음을 수행하십시오.

if [ "${#files[@]}" -eq 1 ] && [ -f "${files[0]}" ]; then
  echo one and only one file matches and it is regular.
fi

하나 이상의 일반 파일과 일치하고 일치하는 모든 파일이 일반 파일인지 확인하려면 다음을 수행하십시오.

only_regular_files() {
  [ "$#" -gt 0 ] || return
  local file
  for file do
    [ -f "$file" ] || return
  done
}

if only_regular_files "${files[@]}"; then
  echo at least one regular file and all are regular.
fi

셸을 통해 zshglob 한정자를 사용하여 파일 형식별로 일치시킬 수 있습니다.

if ()(($#)) $~pattern(N-.); then
  print at least one regular file in the expansion of the pattern.
fi
  • 대조적으로 bash, zsh따옴표가 없는 인수 확장에서는 암시적 분할+glob이 수행되지 않습니다. 여기서는 와일드카드를 요청합니다(분할은 아님) $~pattern.
  • glob이 어떤 파일과도 일치하지 않으면 테스트할 수 없도록 확장 되도록 (N-.)glob 한정자를 추가합니다.Nnullglob.정기적인-테스트를 완료하려면 파일만(다른 유형의 파일 제외)뒤쪽에Symlink 확인을 통해 심볼릭 링크인 파일을 일반 파일과 일치시킵니다(예상한 대로 [ -f "$file" ]).
  • glob의 확장은 익명 함수에 인수로 전달됩니다 . () {body} args여기서 {body}is 입니다 .(($#))
  • ((expr))표현식이 0이 아닌 숫자로 평가되면 true를 반환하는 ksh 스타일 산술 표현식 평가 연산자입니다. 여기서 표현식은 $#위치 인수 수로 확장되는 특수 매개변수인 입니다. 이 경우에는 이 glob 확장으로 생성된 파일 수인 익명 함수에 대한 위치 인수 수입니다.

답변2

[ -f $file ] && echo ok

그러면 변수, wordsplit 및 확장이 확장됩니다.모두파일을 일치시킵니다. 로 끝날 수도 있는데 [ -f filethis filethat ]이는 filethis이항 연산자가 아니므로 오류가 발생합니다.

일치하는 항목이 없고 $file확장이 비어 있는 경우에도 비어 있지 않은 문자열인지 [ -f ]확인하기 위한 테스트로 이를 얻을 수 있습니다. -f네, 결과는 맞습니다.

파일 이름을 배열이나 위치 인수로 확장하고 일치 항목 수를 계산합니다.

file="path with wildcard*"
IFS=
set -- $file
echo "matched $# files"

패턴에 공백이 있는 경우 IFS파일 이름 확장 전에 분할이 발생하므로 여기에서 변경해야 합니다. 따라서 위에는 두 개의 상수 단어와 전역 패턴이 있습니다. 또한 일치하지 않는 패턴도 그대로 유지되므로 이를 확인해야 합니다.

함수에서 숨길 수 있습니다.

only_one() {
    local IFS=
    set -- $1
    if [ $# = 1 ] && [ -f "$1" ]; then return 0; fi
    return 1
}

그런 다음 실행

if only_one "$file"; then 
    ...
fi

답변3

나는 그것을 해결했습니다:
"a.sh" 파일에는 다음이 포함되어 있습니다:

file=('path with wildcard'*)

"b.sh" 파일에는 다음이 포함됩니다.

. a.sh
[ -f "$file" ] && echo ok

결과: OK

관련 정보