find를 사용하여 찾은 파일의 내용을 단일 파일로 병합하려면 어떻게 해야 합니까?

find를 사용하여 찾은 파일의 내용을 단일 파일로 병합하려면 어떻게 해야 합니까?

나는 귀중한 데이터가 들어 있는 파티션을 다시 포맷하여 아픈 곳(매우 심하게)을 스스로 촬영할 수 있었습니다. 물론 의도한 것은 아니었지만 그런 일이 일어났습니다.

그러나 대부분의 데이터를 사용 testdisk하고 복구 했습니다 . photorec이제 모든 데이터가 거의 25,000개의 디렉터리에 분산되어 있습니다. 대부분의 파일은 .txt 파일이고 나머지는 이미지 파일입니다. 각 디렉터리에는 300개 이상의 .txt 파일이 있습니다.

grep.txt 파일에서 특정 문자열을 추출하고 .txt를 사용하여 find파일로 출력할 수 있습니다. 예를 들어 다음 줄을 사용하여 내 데이터가 복구된 파일에 있는지 확인합니다.

find ./recup*/ -name '*.txt' -print | xargs grep -i "searchPattern"

"searchPattern"을 파일로 출력할 수 있지만 이는 단지 패턴만 제공할 뿐입니다. 이것이 내가 정말로 달성하고 싶은 것입니다:

모든 파일을 탐색하고 특정 문자열을 찾으십시오. 파일에서 문자열이 발견되면 파일의 전체 내용을 출력 파일로 변환합니다. 패턴이 여러 파일에서 발견되면 후속 파일의 내용이 이 출력 파일에 추가됩니다. 내가 찾고 있는 패턴을 출력하는 것이 아니라 패턴이 발견된 파일의 전체 내용을 출력하고 싶다는 점에 유의하세요.

나는 이것이 가능하다고 생각하지만 파일에서 특정 패턴을 파악한 후 파일의 모든 내용을 얻는 방법을 모르겠습니다.

답변1

귀하의 목표를 올바르게 이해하면 다음과 같이 원하는 것을 얻을 수 있습니다.

find ./recup*/ -name '*.txt' -exec grep -qi "searchPattern" {} \; -exec cat {} \; > outputfile.txt

*.txt그러면 의 모든 파일을 찾고 ./recup*/, 각 파일을 테스트하고 searchPattern, 일치하면 해당 cat파일을 찾습니다. 모든 ed 파일의 출력 catoutputfile.txt.

각 패턴과 출력 파일에 대해 이를 반복합니다.


일치하는 디렉토리가 많은 경우 ./recup*하나의 디렉토리로 끝날 수 있습니다 argument list too long error. 이 문제를 해결하는 쉬운 방법은 다음을 수행하는 것입니다.

find ./ -mindepth 2 -path './recup*.txt' -exec grep -qi "searchPattern" {} \; -exec cat {} \; > outputfile.txt

이는 전체 경로와 일치합니다. 그래서 ./recup01234/foo/bar.txt일치할 것입니다. 따라서 -mindepth 2일치하지 않습니다 ./recup.txt. 또는 ./recup0.txt.

답변2

패턴을 출력하는 대신 grep에서 "-l"을 사용하여 파일 이름을 출력한 다음 cat에 대한 입력으로 사용할 수 있습니다.

find ./recup*/ -name '*.txt' -print | xargs grep -li "searchPattern" | xargs cat

또는

cat $( find ./recup*/ -name '*.txt' -print | xargs grep -li "searchPattern")

나머지 세부 사항은 귀하가 작성해 주실 수 있을 것 같습니다. 그런데, 파일 이름에 공백이나 기타 이상한 문자가 있을 수 있는 경우(이 특별한 경우는 아니지만 향후 목적을 위해) find에서 -print0을 사용하고, grep에서 -Z를 사용하고, xargs에서 -0 옵션과 결합하여 null을 사용합니다. 개행 대신 파일 이름 사이에 바이트를 추가합니다.

find ./recup*/ -name '*.txt' -print0 | xargs -0 grep -Zli "searchPattern" | xargs -0 cat

답변3

이것은 정확히 최적의 코드는 아니지만 매우 간단하고 효율성이 문제가 되지 않는 경우 잘 작동합니다. 문제는 문자열이 파일에서 이미 발견된 경우에도 파일을 여러 번 grep한다는 것입니다.

먼저 문자열을 검색하고 일치하는 파일을 목록에 작성합니다.

find ./recup*/ -name '*.txt' -execdir grep -il "searchPattern" {} >> /tmp/file_list \;

searchPattern필요에 따라 교체하려면 이 단계를 반복하세요. 그러면 에 있는 일치하는 파일 목록이 생성됩니다 /tmp/file_list.

문제는 파일에 중복이 있을 수 있다는 것입니다. 따라서 중복 항목을 |sort|uniq. 이 구성 요소는 중복 항목을 제거할 수 sort있도록 서로 옆에 배치합니다 . 그런 다음 이러한 파일을 함께 사용할 uniq수 있습니다 (각 파일 이름은 개행 문자로 구분됨 ). 그러므로,catxargs\n

</tmp/file_list sort | uniq | xargs -d "\n" cat > final_file.txt

다른 답변과 달리 여기에는 두 단계와 임시 파일이 있으므로 찾을 패턴이 여러 개인 경우에만 권장됩니다.

답변4

쉘과 환경에 따라 이 작업을 수행할 수 있습니다(bash에서).

while IFS= read -r -d '' file; do
  if grep -qim1 'searchPattern1\|searchPattern2\|searchPattern3' "$file"; then
    cat "$file" >> some/other/file
  fi
done < <(find ./recup*/ -name '*.txt' -print0)

패턴을 기반으로 결과를 분리하려면 다음과 같이 수정할 수 있습니다.

while IFS= read -r -d '' file; do
  if grep -qim1 'searchPattern1' "$file"; then
    cat "$file" >> some/other/file1
  elif grep -qim1 'searchPattern2' "$file"; then
    cat "$file" >> some/other/file2
  elif grep -qim1 'searchPattern3' "$file"; then
    cat "$file" >> some/other/file3
  fi
done < <(find ./recup*/ -name '*.txt' -print0)

관련 정보