grep
1TB의 파일을 검색하는 데 사용하고 있습니다 . 파일 이름을 grep하고 이름을 텍스트 파일에 넣고 싶고 cp
dir 과 일치하는 모든 파일을 원합니다 /home/user/matches
. 모든 파일을 두 번 greping하지 않고 두 작업을 모두 수행하고 싶습니다.
내 생각은 grep을 사용하여 파일 이름 출력을 텍스트 파일에 넣는 것입니다.
grep -ril "xxx" . >> /home/user/matches/output-filename.txt
이제 output-filename.txt
cp에 대한 입력 역할을 하며 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