입력 파일을 사용하여 파일을 복사하여 파일 방향을 읽습니다.

입력 파일을 사용하여 파일을 복사하여 파일 방향을 읽습니다.

grep1TB의 파일을 검색하는 데 사용하고 있습니다 . 파일 이름을 grep하고 이름을 텍스트 파일에 넣고 싶고 cpdir 과 일치하는 모든 파일을 원합니다 /home/user/matches. 모든 파일을 두 번 greping하지 않고 두 작업을 모두 수행하고 싶습니다.

내 생각은 grep을 사용하여 파일 이름 출력을 텍스트 파일에 넣는 것입니다.

grep -ril "xxx" . >> /home/user/matches/output-filename.txt

이제 output-filename.txtcp에 대한 입력 역할을 하며 cp가 한 줄씩 실행되도록 합니다. 어떻게 해야 하나요? 어? 아니면 모든 파일을 두 번 검색하지 않도록 하는 다른 아이디어가 있습니까?

답변1

파일 경로는 0이 아닌 바이트 시퀀스입니다. 텍스트 줄은 물론 텍스트일 필요도 없습니다. 특히 파일 경로

  • 개행 문자를 포함할 수 있습니다.
  • 유효한 문자를 형성하지 않는 바이트 시퀀스를 포함할 수 있습니다.
  • LINE_MAX보다 길 수 있습니다.

GNU 구현 grep( 옵션을 추가한 구현 -r)은 텍스트가 아닌 형식으로 경로를 인쇄할 수 있으며 -Z후처리에 안전합니다. 예를 들어, GNU는 xargs옵션을 사용하여 이 형식을 처리할 수 있습니다 -0:

xargs -r0 -a <(
  grep -rilZ xxx . |
   tee file.list
)  cp -it /home/user/matches --

(이 역시 GNU를 옵션 cp으로 가정합니다 -t)

GNU를 사용하여 사람이 읽을 수 있는 텍스트 형식으로 목록을 인쇄하려면 다음을 수행하십시오 printf.

xargs -r0a file.list printf '%q\n'

1 문자가 표현으로 렌더링되므로 디코딩할 수 없는 바이트를 보장해야 합니다 $'\234'. .$'\n'LINE_MAX​지원하는 행 수에는 제한이 없습니다).

답변2

find한 쌍의 연결된 명령을 사용할 수 있습니다 exec. grep모든 파일(및 일치하는 모든 파일)에 대해 호출 되므로 가장 효율적인 솔루션은 아닐 수 있지만 cp파일 이름의 문자에 관계없이 작동합니다.

mkdir -p ~/matches
find -type f -exec grep -il 'xxx' {} \; -exec cp -p {} ~/matches/ \; > ~/matches/output-filename.txt

답변3

이렇게 사용하세요tee,xargs명령( NULL byte \0파일 이름 구분 기호의 끝으로 사용됨) 및GNU grep:

공백, 개행 등을 사용하여 파일 이름을 처리합니다.

mkdir -p ~/matches
grep -Zril "xxx" . |
    tee ~/matches/output-filename.txt |
    xargs -0 -I {} cp {} ~/matches/

관련 정보