내가 이것을 실행할 때 :
for f in $(grep -r --include=*.directory "search-string"); do echo $f; done;
내가 얻은 검색 결과는 검색 결과 파일 이름에서 공백으로 구분됩니다.
grep 검색 결과에서 공백을 탈출하는 방법은 무엇입니까?
답변1
배열의 파일 목록을 원하고 bash 셸(버전 4.4 이상)을 사용하는 경우 다음을 수행할 수 있습니다.
readarray -td '' files < <(
grep -rlZ --include='*.directory' "search-string" .
)
쉘 포함 zsh
:
files=(${(0)"$(grep -rlZ --include='*.directory' "search-string" .)"})
다음을 사용하여 반복합니다.
for file in "${files[@]}"; do
printf '%s\n' "$file"
done
를 사용하면 zsh
다음을 통해 중간 배열을 건너뛸 수 있습니다.
for file in ${(0)"$(grep -rlZ --include='*.directory' "search-string" .)"}; do
printf '%s\n' "$file"
}
따옴표가 없는 단어 확장(예: $f
또는 $(...)
)은 매우 특별한 의미를 가지며 bash
일반적으로 원하는 것이 아니며 파일 이름은 NUL을 제외한 모든 바이트 값을 포함할 수 있으므로 표현할 때 NUL이라고도 0
해도 0
괜찮습니다. 고유하게 구분된 파일 경로 목록 구분된 바이트 스트림으로 사용하는 것이 안전합니다. 이것이 GNU의 -Z
/ 옵션의 목적입니다.--null
grep
다음과 같은 간단한 셸을 사용하면 GNU의 출력을 사용하여 셸에서 참조하는 파일 이름 목록을 생성하여 셸 코드로 평가할 dash
수 있습니다.gawk
grep
sh
eval set -- "$(
grep -rlZ --include='*.directory' "search-string" . |
gawk -v RS='\0' -v ORS=' ' -v q="'" '
{gsub(q, q "\\" q q); print q $0 q}'
)"
for file do
printf '%s\n' "$file"
done
파일 이름에 개행 문자가 포함되지 않는다고 보장할 수 있다면 다음과 같이 단순화할 수 있습니다.
IFS='
'
set -o noglob
for file in $(grep -rl --include='*.directory' "search-string" .); do
printf '%s\n' "$file"
done
set -o noglob
파일 이름에 *
, ?
, [
( \
셸 및 셸 버전에 따라 , 및 더 많은 glob 연산자)도 포함되지 않는다고 보장할 수 있으면 건너뛸 수 있습니다.
답변2
파일 경로에 개행 문자가 없다고 확신하는 경우 단어 분할을 개행 문자로 제한할 수 있습니다.
oldIFS="$IFS"
IFS=$'\n'
for f in $(grep -r --include=*.directory "search-string"); do
echo "$f"
done
IFS="$oldIFS"
답변3
grep
GNU 사람들은 파일을 찾는 옵션을 제공했을 때 정말 실수를 저질렀습니다. sed, awk, cat, tr, wc 및 기타 모든 UNIX 도구에 대해 동일한 기능을 제공할 계획이 없으며 기존 도구가 수행하는 다른 작업(예: 파일 정렬)에 grep 옵션을 제공할 계획도 없기를 바랍니다. ), 문자열 바꾸기, 문자 번역, 문자 수 계산 등을 수행합니다. 다음을 수행할 수 있는 아주 좋은 UNIX 도구가 있습니다.찾다파일의 이름은 매우 분명합니다 find
.
while IFS= read -rd '' file; do
echo "$file"
done < <(find . -name '*.directory' -exec grep -lZ 'search-string' {} +)
위의 경우 NUL 종료 입력/출력을 사용하려면 (이미 사용 중인) GNU 도구가 필요합니다. 파일 이름에 개행 문자가 없으면 표준 도구를 대신 사용할 수 있습니다.