xz로 압축된 4개의 매우 큰 텍스트 파일이 있다고 가정해 보겠습니다.
file1.log.xz
file2.log.xz
file3.log.xz
file4.log.xz
내가 하고 싶은 건 연결이야압축되지 않은이 4개 파일의 내용을 새 파일로 병합합니다 file.xz
. 문제는 이상적으로는 중간 파일을 확인할 필요가 없다는 것입니다.
이러한 파일은 크기가 기가바이트 단위로 측정되는 매우 큰 로그 파일입니다. 압축하면 100MB 미만이지만, 4개 파일을 모두 확장한 다음 다시 연결하려면 압축되지 않은 파일을 위해 최소 30GB의 저장 공간이 필요합니다. 물론, cat
압축되지 않은 모든 파일을 xz
다시 압축 할 수 있습니다.
cat file1.log file2.log file3.log file4.log | xz -ve9 - > newfile.log.xz
나 어떻게 연결하는지 알아둘한 파일은 압축 해제되고 다른 파일은 압축되었다고 가정하고 명령줄에서 중간 파일 없이 파일을 봅니다.
xz -d -c file2.log.xz | cat file1.log - | xz -ve9 - > files1and2.log.xz
하지만 이 방법은 하나의 파일에서만 작동하며, 파일 중 하나의 압축을 풀어야 합니다.
다양한 .xz 파일을 함께 넣는 것이 가능한지 잘 모르겠습니다 cat
. 서로 다른 매개변수를 사용하여 압축되었을 수 있다고 가정해 보겠습니다.
높은 수준에서는 다음과 같은 질문을 던질 수 있습니다. 여러(셋 이상) 명령의 출력을 가져와서 이러한 출력을 연결하고 중간 파일 없이 다른 프로세스로 파이프할 수 있습니까? (가설 시나리오: 내가 뭔가를 하고 있다고 상상해 보세요.처리4개의 매우 큰 파일 모두에 대해 stdout으로 출력하고 출력을 다른 압축 파일에 저장하려는 스크립트를 사용합니다. )
쉘 명령만 사용하여 이를 수행할 수 있습니까?
답변1
문서 xz
에 따르면
.xz
파일은 있는 그대로 연결할 수 있습니다 .xz
이러한 파일은 단일 파일인 것처럼 압축이 풀립니다.xz
.
내 테스트에 따르면 다른 파일이 다른 옵션으로 압축된 경우에도 작동합니다.
cat -- *.log.xz > newfile.log.xz
잘 작동할 겁니다.
보다 일반적인 질문에 대답하려면 복합 명령의 출력을 파이프하면 됩니다.예를 들어
for file in -- *.log.xz; do xzcat -- "$file"; done | xz -ve9 > newfile.log.xz
또는 하위 쉘. 이렇게 하면 로그 파일을 다시 압축하기 전에 원하는 처리를 수행할 수 있습니다. 그러나 기본적인 경우에는 다음을 실행하여 모든 파일의 압축을 풀고 다시 압축할 수 있습니다.
xzcat -- *.log.xz | xz -ve9 > newfile.log.xz
추가하면 -f
압축되지 않은 파일에도 작동합니다.
xzcat -f -- uncompressed.log *.log.xz | xz -ve9 > newfile.log.xz
압축되지 않은 로그와 압축된 로그를 병합할 수 있습니다.
답변2
노력하다
for x in *.log.xz
do
xz -d -c "$x"
done | xz -ve9 - > newfile.log.xz
(물론 온라인으로도 가능합니다.)
압축되지 않은 새 파일을 추가하려면 서브쉘( ()
) 을 사용하십시오.
( cat newfile.log
for x in *.log.xz
do
xz -d -c "$x"
done ) | xz -ve9 - > newfile.log.xz
답변3
xzcat -f
귀하의 질문의 첫 번째 부분에 대한 답변입니다. 하지만 당신 말이 맞습니다. cat *xz | xzcat
일부 파일이 -F lzma
.
더 높은 수준에서는 다음과 같은 질문 자체를 할 수 있습니다. 여러(셋 이상) 명령의 출력을 가져와서 이러한 출력을 연결하고 중간 파일 없이 다른 프로세스로 파이프할 수 있습니까?
여기서 문제는 중간 출력을 파일에 저장하지 않는 경우입니다.하다저장하시나요?
RAM에 저장되는 경우 사용 가능한 RAM 용량에 따라 제한됩니다. 이 값을 초과하면 컴퓨터가 곧 지옥으로 갈 것입니다.
tmpfs
GNU Parallel은 이를 임시 파일에 저장하지만, 파일 시스템 에 넣으면 기본적으로 RAM에 저장됩니다.
mkdir mytmp
sudo mount tmpfs mytmp -t tmpfs -o rw,size=3P
parallel --tmpdir mytmp seq {}00000000 {}99999999 ::: 1 2 | grep 0000000
그러나 출력을 한 줄씩 혼합할 수 있는 경우 실행 중인 각 프로그램에 대해 RAM에 한 줄만 저장하면 됩니다.
GNU Parallel(>버전 20170822)이 수행하는 작업은 다음과 같습니다.
parallel --lb seq {}00000000 {}99999999 ::: 1 2 | grep 0000000
세 번째 해결 방법은 빠른 압축기를 사용하여 임시 파일(예 pzstd
: pigz
, lz4
, lzop
)을 압축하는 것입니다.
parallel --compress seq {}00000000 {}99999999 ::: 1 2 | grep 0000000
(GNU Parallel은 설치된 고속 압축기를 자동으로 감지합니다).
답변4
@Archemar가 이 문제에 대해 이야기했지만 실제로 제목의 질문에 직접적으로 답변한 사람은 없는 것 같습니다.
중간 파일 없이 여러 명령의 결과를 다른 명령으로 연결하고 파이프하는 방법은 무엇입니까?
그리고 게시물에서 이를 반복하세요.
더 높은 수준에서는 다음과 같은 질문 자체를 할 수 있습니다. 여러(셋 이상) 명령의 출력을 가져와서 이러한 출력을 연결하고 중간 파일 없이 다른 프로세스로 파이프할 수 있습니까?
Archemar가 제안한 것처럼, 요청한 작업을 수행하는 일반적인 방법은 서브쉘을 사용하는 것입니다.
배시 구문:
(
command_one
command_two
command_three
...
command_N
) | next_command