5백만 개의 파일을 효율적으로 병합

5백만 개의 파일을 효율적으로 병합

잘못된 계획으로 인해 내 디렉토리에는 500만 개가 넘는 파일이 포함되어 있으며 총 용량은 약 20GB입니다. 각 파일의 맨 위에는 32줄의 쓰레기가 포함되어 있으며 그 뒤에는 알 수 없는 수의 중요한 데이터 줄이 있습니다.

모든 중요한 데이터를 하나의 파일로 통합하고 싶습니다.

나는 이것을하고있다 :

for i in $(find); do tail -n +32 $i >> ../all.txt; done

all.txt는 초당 약 0.5MB만 증가합니다. 이 작업을 수행하는 더 빠른 방법이 있습니까? 또한 작업을 마치기 전에 디스크 공간이 부족할 수 있으므로 파일을 삭제하는 것이 편리할 것입니다. X

어떤 제안이라도 감사하겠습니다.

답변1

언제든지 파일을 삭제해야 하는 경우 작성한 내용이 이미 빠른 삭제 방법입니다. 한 가지 최적화는 를 find사용하여 파일을 나열하는 대신 파일 내용을 나열하는 데 사용할 수 있다는 것입니다 *. 파일은 추가 처리 시간을 발생시키지 않고 디렉터리 목록에 나열되기 때문입니다 find. 즉, 다음과 같이 작성합니다.

for i in *; do tail -n +3 $i >> ../x; rm $i; done

그러나 병합을 완료하기 전에 해당 항목을 제거할 수 있고 어떤 콘텐츠가 어떤 파일에서 왔는지 유지하려는 경우 한 번에 구문 분석하여 여러 항목(셸에서 허용하는 만큼)을 추적하는 방법이 있습니다. 이를 수행하는 명령은 다음과 같습니다.

find . -exec tail -n +3 {} >> ../x +

마지막으로 한 번에 하나씩이 아닌 여러 파일 이름을 한 번에 전달하라는 +메시지가 표시됩니다 . find이렇게 하면 (호출되는 인스턴스 수가 훨씬 적어지기 때문에) 성능이 크게 향상되지만 tail출력 파일에는 여전히 다음과 같은 내용이 있습니다.

==> ./filename <==

한 파일이 끝나고 다음 파일이 시작될 때마다 인쇄합니다. 또한 이러한 파일은 삭제되지 않습니다.

약간의 속도를 희생하면서 위 줄을 제거하려면 다음을 통해 실행할 수 있습니다.

find . -exec awk 'FNR>32' {} + 

(댓글로 제안해 주신 dave_thompson에게 감사드립니다).

마지막으로, 어떤 정보가 어떤 파일에서 왔는지 나열하는 출력을 선호하고 언제든지 제거하려는 경우 iruvar의 답변을 사용하여 두 개의 \;''를 +'''로 바꿀 수 있습니다(내 원래 답변은 무엇을 해야할지 iruvar가 실제 명령을 제공합니다.

답변2

프로세스가 IO 바인딩될 수 있으므로 최적화 루프는 기껏해야 약간의 개선을 가져올 것입니다. 파일에 대해 깊이 우선 작업을 수행할 수 있는 경우 tailrm호출을 매체로 롤링 find하고 진행하면서 삭제할 수 있습니다.

GNU 사용 find:

find . -type f -exec tail -n +32 {} \; -delete >../all.txt

이상적으로는 교체를 통해 여러 파일을 한 번에 전달할 수 있기를 원 find하지만 제대로 작동하지 않는 것 같습니다.tail\;+-delete

find선택 -delete의 부족

find . -type f -exec tail -n +32 {} \; -exec rm {} \; >../all.txt

또는 GNU 시스템에서는 여러 파일을 수신할 때 파일 헤더 인쇄를 억제하기 -q위해 to에 전달할 수 있습니다 .tailtail

find . -type f -exec tail -q -n +32 {} + -exec rm {} + >../all.txt    

참고 - 이 -exec rm마지막 -delete만트라는 아마도 가장 효율적일 것입니다.

관련 정보