목록에서 grep 파일 files.txt) $ grep

몇 백 개의 파일 목록에 대해 grep을 실행하려고합니다.

$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php

그러나 파일에서 찾은 문자열을 파악하고 있지만 다음은 파일을 검색하지 않습니다.

$ grep -i 'foo' <(cat files.txt)

$ grep -i 'foo' admin.php
The foo was found

파일 -f에서 패턴 을 읽을 플래그에 익숙 합니다. 그러나 입력 파일 을 읽는 방법은 무엇입니까?

형식 cp을 지원하는 것처럼 파일을 임시 디렉토리에 복사하고 파일을 <(cat files.txt)grepping하는 끔찍한 해결 방법을 고려했습니다 . 셜리가 더 좋은 방법이 있습니다.



답변

파일 자체가 아닌 파일 이름 목록을 잡고있는 것 같습니다. <(cat files.txt)파일 만 나열합니다. 시도 <(cat $(cat files.txt))사실에을 연결하고 단일 스트림로를 검색하거나

grep -i 'foo' $(cat files.txt)

모든 파일을 grep합니다.

그러나 목록에 파일이 너무 많으면 인수 수에 문제가있을 수 있습니다. 그 경우에 나는 단지 쓸 것입니다

while read filename; do grep -Hi 'foo' "$filename"; done < files.txt

답변

xargs grep -i -- foo /dev/null < files.txt

파일이 비어 있거나 줄 바꿈으로 구분되어 있다고 가정합니다 (따옴표 나 역 슬래시를 사용하여 구분 기호를 이스케이프 할 수 있습니다). GNU xargs를 사용하면 구분 기호를 지정 -d하여 인용 처리를 비활성화 할 수 있습니다 .

(unset -v IFS; set -f; grep -i -- foo $(cat files.txt))

파일이 공간, 탭 또는 줄 바꿈으로 구분되어 있다고 가정하면 (다른 구분 기호를 할당하여 다른 구분 기호를 선택할 수는 있지만 탈출 할 수는 없습니다) IFS ). 대부분의 시스템에서 파일 목록이 너무 크면 실패합니다.

또한 파일 중 어느 것도 호출되지 않는다고 가정합니다 -.


답변

stdin에서 파일 이름 목록을 읽으려면을 사용할 수 있습니다 xargs. 예 :

cat files.txt | xargs -d'\n' grep -i -- 'foo'

기본적 xargs으로 공백으로 구분 된 표준 입력에서 항목을 읽습니다. 이 명령 -d'\n'은 개행 문자를 인수 구분자로 사용하도록 지시하므로 공백이 포함 된 파일 이름을 처리 할 수 ​​있습니다. (Stéphane Chazelas가 지적했듯이, 이것은 GNU 확장입니다). 그러나 개행을 포함하는 파일 이름에는 대처할 수 없습니다. 이를 처리하기 위해서는 약간 더 복잡한 접근법이 필요합니다.

FWIW 에서이 접근법은 while readbash의 read명령이 매우 느리기 때문에 루프 보다 다소 빠릅니다. 문자별로 데이터를 읽습니다.xargs 읽지 만 입력을보다 효율적으로 읽습니다. 또한 각 호출이 여러 파일 이름을 수신 할 때마다 필요한 xargs만큼만 grep명령을 호출 grep하므로 각 파일 이름에 대해 개별적으로 호출하는 것보다 효율적 입니다.

자세한 내용은 xargs 매뉴얼 페이지 와 xargs 정보 페이지를 참조하십시오.


답변

xargsfiles.txt옵션 으로 파일에서 항목 (예 : 목록)을 읽을 수 있습니다 .

   --arg-file=file
   -a file
          Read items from file instead of standard input.  If you use this
          option, stdin remains unchanged when commands are  run.   Other
          wise, stdin is redirected from /dev/null.

따라서 이것은 작동해야합니다.

xargs -a files.txt grep -i 'foo'

또는 파일 이름의 공백

xargs -d'\n' -a files.txt grep -i 'foo'
xargs -I{} -a files.txt grep -i 'foo' {}

답변

당신은 또한 할 수 있지만 Orion의 예는 가장 간단합니다.

for i in $(cat files.txt); do grep -i 'foo' $i ; done

(files.txt에 나열된 각 파일에 대해 grep 명령을 실행하십시오.)