zstd -r 폴더 -o 출력.zst로 인해 단일 파일에서 여러 파일을 분리하는 방법은 무엇입니까?

zstd -r 폴더 -o 출력.zst로 인해 단일 파일에서 여러 파일을 분리하는 방법은 무엇입니까?

매뉴얼을 충분히 읽지 않아서 다음 명령을 실행했습니다.

$ zstd -r folder -o output.zst

다음 명령은 출력이라는 파일을 제공합니다.

$ unzstd output.zst 

출력 파일에는 연결된 폴더에 있는 파일의 전체 내용이 포함됩니다.

단일 파일을 여러 개의 원시 파일로 나눌 수 있는 도구나 프로그램이 있습니까?

이것이 내가 백업해야 할 유일한 백업 파일입니다.

편집: 내가 실제로 실행해야 하는 것(에 따르면이 스레드) 예

# for tar version 1.31 and above
$ tar --zstd -cf output.tar.zst folder

# for tar version < 1.31
$ tar --use-compress-program zstd -cf output.tar.zst folder

답변1

이 질문도 올렸어요zstd github 문제내가 배운 것은 다음과 같습니다.청록색 4973.

모든 압축된 프레임은 동일한 파일 output.zst에 즉시 저장됩니다.

적어도 이론상으로는 각 프레임을 분리하여 각 파일의 경계를 찾는 방법이 있지만, 또 다른 문제는 프레임 중 어느 것도 파일 이름이나 디렉터리 트리의 위치를 ​​포함하지 않는다는 것입니다. 따라서 이름 없는 파일이 잔뜩 남게 됩니다.

올바른 아카이브 방법은 zstd를 파일 메타데이터 저장을 담당하는 tar와 결합하는 것입니다.

현재 프레임을 분리할 수 있는 도구나 프로그램은 없습니다. 그러나 누군가는 그것을 사용할 수 있습니다 lz4frame.h.

기본적으로 CLI는 모든 프레임을 동일한 압축 해제 파일로 연속적으로 압축 해제합니다.

...직접 프로그래밍하고, ... ZSTD_decompressStream()API를 사용하세요.

답변2

이 Github 문제의견에서는 코드를 사용하여 파일을 재현할 것을 제안합니다(파일 이름 및 폴더 계층 구조 없이).

#undef NDEBUG
#define ZSTD_STATIC_LINKING_ONLY

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <zstd.h>

static uint64_t get_file_size(char const* filename) {
  FILE* f = fopen(filename, "rb");
  assert(f != NULL);
  int ret = fseek(f, 0L, SEEK_END);
  assert(ret == 0);
  long int const size = ftell(f);
  assert(size >= 0);
  fclose(f);
  return (uint64_t)size;
}

static void read_file(char const* filename, void* buffer, size_t size) {
  FILE* f = fopen(filename, "rb");
  assert(f != NULL);
  size_t const read = fread(buffer, 1, size, f);
  assert(read == size);
  char tmp;
  assert(fread(&tmp, 1, 1, f) == 0);
  fclose(f);
}

static size_t decompress_one_frame(char const* inputPtr, char const* inputEnd, char const* outputPrefix, int idx) {
  size_t const inputSize = (size_t)(inputEnd - inputPtr);
  size_t const compressedSize = ZSTD_findFrameCompressedSize(inputPtr, inputSize);
  assert(!ZSTD_isError(compressedSize));

  size_t const decompressBound = ZSTD_decompressBound(inputPtr, compressedSize);
  assert(decompressBound != ZSTD_CONTENTSIZE_ERROR);
  void* const decompressed = malloc(decompressBound);
  assert(decompressed != NULL);

  size_t const decompressedSize = ZSTD_decompress(decompressed, decompressBound, inputPtr, compressedSize);
  assert(!ZSTD_isError(decompressedSize));


  size_t const outputFileSize = strlen(outputPrefix) + 11;
  char* const outputFile = malloc(outputFileSize);
  assert(outputFile != NULL);
  {
    size_t const written = snprintf(outputFile, outputFileSize, "%s%d", outputPrefix, idx);
    assert(written < outputFileSize);
  }
  {
    FILE* f = fopen(outputFile, "wb");
    size_t const written = fwrite(decompressed, 1, decompressedSize, f);
    assert(written == decompressedSize);
    fclose(f);
  }

  free(outputFile);
  free(decompressed);
  return compressedSize;
}

int main(int argc, char** argv) {
  if (argc != 3) {
    fprintf(stderr, "USAGE: %s FILE.zst OUT-PREFIX\n", argv[0]);
    fprintf(stderr, "Decompresses a zstd file containing more than one frame to ${OUT-PREFIX}0, ${OUT-PREFIX}1, ...\n");
    return 1;
  }
  char const* const inputFile = argv[1];
  char const* const outputPrefix = argv[2];

  size_t const inputSize = get_file_size(inputFile);
  char* const input = malloc(inputSize);
  assert(input != NULL);
  read_file(inputFile, input, inputSize);

  char const* inputPtr = input;
  char const* const inputEnd = input + inputSize;
  int idx = 0;
  while (inputPtr < inputEnd) {
    size_t const compressedSize = decompress_one_frame(inputPtr, inputEnd, outputPrefix, idx);
    inputPtr += compressedSize;
    ++idx;
  }
  assert(inputPtr == inputEnd);
  free(input);
  return 0;
}

이 앱은 당신에게 도움이 될 것입니다. 라는 파일에 쓰고 unzstd.clibzstd가 설치되어 있으면 다음을 cc unzstd.c -lzstd -o unzstd사용하여 컴파일할 수 있습니다. 그런 다음 압축을 풀려는 파일이 있으면 다음을 input.zst실행할 수 있습니다.

mkdir output
./unzstd input.zst output/
ls output/

압축한 각 입력 파일에 대해 압축 순서에 따라 출력/0, 출력/1 등의 이름을 붙인 출력 파일을 생성합니다. 따라서 파일 이름과 디렉터리 구조는 손실되지만 파일의 모든 내용은 다시 복구됩니다.

관련 정보