중간 파일 없이 여러 명령의 결과를 다른 명령으로 연결하고 파이프하는 방법은 무엇입니까?

중간 파일 없이 여러 명령의 결과를 다른 명령으로 연결하고 파이프하는 방법은 무엇입니까?

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 용량에 따라 제한됩니다. 이 값을 초과하면 컴퓨터가 곧 지옥으로 갈 것입니다.

tmpfsGNU 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

관련 정보