큰따옴표로 묶인 인수(파일 이름 표시)는 공백이 포함된 경우 도움이 되지 않습니다.

큰따옴표로 묶인 인수(파일 이름 표시)는 공백이 포함된 경우 도움이 되지 않습니다.

큰따옴표로 묶인 인수는 특정 파일 이름을 반복할 때 파일 이름이 손상되는 것을 방지하지 않습니다.

$ mkdir temp
$ cd temp/
$ touch a\ b
$ for f in $(find .) ; do echo "$f" ; done
.
./a
b

답변1

이 지시문은 for f in $(find .)요소 목록을 공백을 기준으로 반복하여 분할합니다. zsh와 같은 최신 쉘에서는확장 플래그로 사용할 수 있습니다.

for f in "${(@f)$(find .)}" ; do echo "$f" ; done

머물면 bash우리가 이 문제를 해결할 수 있어요다른 질문에서 언급했듯이find결과를 변수에 할당하는 동안 입력 구분 기호(요소를 구분하는 데 사용되는 문자)를 임시로 수정합니다 . 일시적으로 고빙을 비활성화하면 *해당 문자 와 ​​같은 와일드카드 문자의 확장이 방지됩니다 .

set -f  # Disable globbing.
IFS=$(echo -e '\0') files=( $(find .  -print0) )  # Read newline separated files into an array.
for f in ${files[@]}; do echo $f; done
set +f  # Reenable globbing.

그러나 이것은 단지 문제를 변화시켰을 뿐이고, 이제 파일 이름에 개행 문자가 있으면 작동하지 않습니다. 아마도 모든 파일 시스템에서 금지되는 것 중 하나는 널 문자일 것입니다. 그러나 bash의 변수는 이를 보유하지 않을 수 있으므로 에 할당할 수 없습니다 IFS.

find또는 xargs를 사용하여 경로를 다른 프로그램 에 전달할 수 있습니다 . null 문자를 구분 기호로 사용하는 to -print0명령을 사용 find하고 -0to로 전환합니다 . 한 번에 하나의 파일 이름을 처리하기 위해 호출 에 xargs추가되었습니다 .-n1xargs

find . -print0 | xargs -0 -n1 echo

답변2

인수의 변수 대체를 큰따옴표로 묶었 echo지만 루프 반복 목록의 명령 대체는 큰따옴표로 묶지 않았습니다 for. 여기서 공백과 기타 불쾌한 문제가 발생합니다.

find개행 문자가 파일 이름의 일부인지 구분 기호의 일부인지 알 수 없기 때문에 출력을 구문 분석하는 완전히 신뢰할 수 있는 방법은 없습니다 .

find파일 이름에 개행 문자가 포함되어 있지 않다고 가정할 수 있는 경우 \[?*필드 구분 기호를 개행 문자로만 제한하고(공백과 탭 보호를 위해) 와일드카드를 꺼서(보호를 위해) 출력을 분할하도록 배열할 수 있습니다.

IFS='
'; set +f
for f in $(find .); do
  unset IFS; set +f
  echo "$f"
done
unset IFS; set +f

하지만 이를 수행하는 더 좋은 방법이 있습니다. 안정적으로 사용하는 가장 쉬운 방법 find은 출력을 구문 분석하는 대신 명령을 실행하도록 하는 것입니다. 메타데이터가 아직 캐시에 있는 동안 파일이 처리될 가능성이 높으므로 속도가 더 빨라질 수도 있습니다.

find . -exec echo {} \;

쉘 명령이 필요한 경우 쉘을 명시적으로 호출하십시오. 인용에 주의하십시오. 파일 이름을 쉘에 인수로 전달하고, 쉘 명령에 삽입하려고 시도하지 마십시오.

find . -exec sh -c 'echo "$0"' {} \;

각 파일에 대해 셸 인스턴스를 호출하는 대신 셸 호출을 그룹화하고 여러 파일을 반복할 수 있습니다. 이 find명령은 집계를 수행하고 명령줄 길이 제한이 초과되지 않도록 합니다. $0파일 $1등에 대한 더미 인수를 전달하는 것을 잊지 마십시오 .

find . -exec sh -c 'for x; do echo "$x"; done' _ {} +

ksh93, bash 또는 zsh를 사용하는 경우 재귀 와일드카드 기능을 사용할 수 있습니다. 즉, **/PATTERN디렉터리와 해당 하위 디렉터리에서 와일드카드 패턴을 재귀적으로 검색합니다. ksh93에서는 먼저 실행해야 합니다 set -o globstar. Bash에서는 shopt -s globstar이를 먼저 실행 해야 하며 **디렉터리의 심볼릭 링크 내에서도 반복된다는 점에 유의하세요.

for f in **/*; do
  echo "$f"
done

Zsh도 있습니다글로벌 예선대부분의 용도에 적용됩니다 find. 다른 껍질에는 이런 것이 없습니다.

관련 정보