목록 파일에 공백이 있는 파일 이름을 "grep"으로 파이프하는 방법은 무엇입니까?

목록 파일에 공백이 있는 파일 이름을 "grep"으로 파이프하는 방법은 무엇입니까?

첫째, 내가 cygwin을 사용하고 있다는 사실이 여기서 매우 관련성이 높다고 생각합니다.

이론적으로 나는 이 작업을 수행하는 방법을 이미 알고 있습니다.

cat file | xargs grep pattern

문제는 일부 파일 경로 file에 공백이 있다는 것입니다. 파일은 다음과 같습니다.

subdir/foo/bar.html
subdir/f o o/ba r.html
subdir/~foo/bar.html

이로 인해 오류가 발생합니다. 이 문제를 해결하는 방법을 읽었습니다. use . 그러나 출력을 null로 끝나는 줄로 xargs -0만드는 방법을 모르기 때문에 전체 파일을 한 줄로 압축한다는 의미라고 생각했습니다. cat결과적으로 다음과 같은 오류가 발생합니다.

xargs: argument line too long

고쳐 쓰다:내가 읽고 있던 파일에 더 이상 존재하지 않는 일부 경로가 있는 것으로 나타났습니다. 공교롭게도 이 경로들은 모두 하나씩 있어서 ~이것이 문제인 줄 착각했습니다. 이 문서는 존재하지 않는 것으로 밝혀졌습니다. 그래도 우주에 관한 모든 것은 남아 있습니다.

답변1

xargs -d '\n'입력 파일에 한 줄에 하나의 파일 이름이 포함된 경우에 사용됩니다. 예를 들어

xargs -d '\n' grep pattern < file

파일 이름이 "내 홈 디렉토리"로 시작하는 경우 먼저 이 기호를 실제 홈 디렉토리로 바꿔야 ~합니다 . ~예를 들어:

sed -e "s=^~=$HOME=" file | xargs -d '\n' grep pattern

이 sed 스크립트는 큰따옴표로 묶여 있습니다.생각하다변수를 $HOMEsed 스크립트에 삽입하고 /s가 포함되므로 이를 연산자의 구분 기호로 사용합니다 ( =그러나 그럴 가능성은 낮음 ).s$HOME=

또는 를 사용하는 경우 xargs 옵션과 함께 findfind 옵션을 사용하세요 . 예를 들어-print0-0

find ... -print0 | xargs -0 grep pattern

아니면 그냥 find -exec옵션을 사용하세요:

find ... -exec grep pattern {} +

답변2

다른 답변에서 언급했듯이 xargs -d '\n'이것이 선호되는 솔루션입니다. (내 생각에는 이것이 바람직하며 이렇게 xargs해야 합니다.기본, 그러나 그것은 또 다른 이야기입니다. )

그러나 모든 버전이 xargs지원되는 것은 아닙니다 -d. 작동하지 않는 방법에 갇혀 있다면 시도해 볼 수 있습니다.

tr '\n' '\0' < file | xargs -0 grep pattern

(옛날에는 tr이와 같이 null 문자를 대체할 수 없는 버전이 있었지만 오늘날에는 이러한 문자를 접할 가능성이 거의 없습니다.)

답변3

기억하세요: xargs파일의 전체 내용은 grep에 대한 명령줄 인수로 사용됩니다... 귀하가 받는 오류는 파일에 너무 많은 파일 이름으로 인해 명령줄이 너무 길어서 발생했을 수 있습니다.

콘텐츠가 패턴과 일치하는 파일을 검색하려면 다음과 같은 반복 접근 방식을 사용하는 것이 좋습니다.

gcolangelo@debian-test:/tmp$ cat test_files 
/dir1/file1 with space
/dir2/file2 with space
/dir3 with space/file3

gcolangelo@debian-test:/tmp$ while read filepath ; do echo "-- coin ${filepath} --" ; done < test_files 
-- coin /dir1/file1 with space --
-- coin /dir2/file2 with space --
-- coin /dir3 with space/file3 --
-- coin  --

답변4

어떤 경우에는 while루프를 사용하는 것이 더 나을 수도 있습니다 xargs(예: 여러 명령을 실행하려는 경우).

while IFS= read -r file <&3
do
    grep -- pattern "$file" 3<&-
done 3< file

grep그러나 파일당 하나씩 호출한다는 점에 유의하세요.

관련 정보