{"id":32210391,"url":"https://github.com/martinellimarco/t2sz","last_synced_at":"2026-03-01T22:05:23.096Z","repository":{"id":44960973,"uuid":"321473529","full_name":"martinellimarco/t2sz","owner":"martinellimarco","description":"Compress a file into a seekable zstd with special handling for .tar archives","archived":false,"fork":false,"pushed_at":"2026-02-28T22:21:13.000Z","size":684,"stargazers_count":75,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-28T23:28:21.616Z","etag":null,"topics":["compression","seekable","tools","zstd"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinellimarco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-14T21:09:27.000Z","updated_at":"2025-11-04T07:34:32.000Z","dependencies_parsed_at":"2022-08-12T11:40:35.540Z","dependency_job_id":null,"html_url":"https://github.com/martinellimarco/t2sz","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/martinellimarco/t2sz","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinellimarco%2Ft2sz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinellimarco%2Ft2sz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinellimarco%2Ft2sz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinellimarco%2Ft2sz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinellimarco","download_url":"https://codeload.github.com/martinellimarco/t2sz/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinellimarco%2Ft2sz/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29986242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T21:06:37.093Z","status":"ssl_error","status_checked_at":"2026-03-01T21:05:45.052Z","response_time":124,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compression","seekable","tools","zstd"],"created_at":"2025-10-22T06:31:55.873Z","updated_at":"2026-03-01T22:05:23.089Z","avatar_url":"https://github.com/martinellimarco.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://github.com/martinellimarco/t2sz/workflows/Test%20Build/badge.svg)](https://github.com/martinellimarco/t2sz/actions)\n[![License](https://img.shields.io/badge/license-GPLv3-green.svg)](https://github.com/martinellimarco/t2sz/blob/main/LICENSE)\n[![t2sz](https://snapcraft.io/t2sz/badge.svg)](https://snapcraft.io/t2sz)\n[![AUR version](https://img.shields.io/aur/version/t2sz)](https://aur.archlinux.org/packages/t2sz/)\n\n# t2sz\nIt compresses a file into a seekable [zstd](https://github.com/facebook/zstd) splitting the file into multiple frames.\n\nIf the file is a tar archive it compresses each file in the archive into an independent frame, hence the name: tar 2 seekable zstd.\n\nIt operates in two modes. Tar archive mode and raw mode.\n\nBy default it runs in tar archive mode for files ending with `.tar`, unless `-r` is specified.\n\nFor all other files it runs in raw mode.\n\nIn tar archive mode it compresses the archive keeping each file in a different frame, unless `-s` or `-S` is used.\n\nThis allows fast seeking and extraction of a single file without decompressing the whole archive.\n\nWhen `-s SIZE` is used in tar mode, if the size of the file being compressed into a block is less than `SIZE` then another one will be added in the same block, and so on until the sum of the sizes of all files packed together is at least `SIZE`. A file will be never split as `SIZE` is just a minimum value.\n\nWhen `-s SIZE` is used in raw mode then it defines exactly the input block size and bigger inputs will be split in blocks of this size accordingly. If there isn't enough input data the last block will be smaller.\n\nWhen `-S SIZE` is used, files bigger than `SIZE` will be split in blocks of `SIZE` length. It is available only in tar mode and ignored in raw mode.\n\nThe compressed archive can be decompressed with any Zstandard tool, including `zstd`.\n\nTo take advantage of seeking see the following projects:\n- C/C++ library:  [libzstd-seek](https://github.com/martinellimarco/libzstd-seek)\n- Python library: [indexed_zstd](https://github.com/martinellimarco/indexed_zstd)\n- FUSE mount:     [ratarmount](https://github.com/mxmlnkn/ratarmount)\n\n\n## Build\n\nYou'll need `libzstd-dev`\n\n```bash\nsudo apt install libzstd-dev\n```\n\n```bash\ngit clone https://github.com/martinellimarco/t2sz\nmkdir t2sz/build\ncd t2sz/build\ncmake .. -DCMAKE_BUILD_TYPE=\"Release\"\nmake\n```\n\nInstall with\n\n```bash\nsudo make install\n```\n\nOr if you want a debian package you can run\n\n```bash\ncpack\n```\n\nthen install it with\n\n```bash\nsudo dpkg -i t2sz*.deb\n```\n\n## Usage\n\n```commandline\nUsage: t2sz [OPTIONS...] [TAR ARCHIVE | -]\n\nUse '-' as the input filename to read from standard input.\n\nExamples:\n        t2sz any.file -s 10M                        Compress any.file to any.file.zst, each input block will be of 10M\n        t2sz archive.tar                            Compress archive.tar to archive.tar.zst\n        t2sz archive.tar -o output.tar.zst          Compress archive.tar to output.tar.zst\n        t2sz archive.tar -o -                       Compress archive.tar to standard output\n        t2sz -r - -o out.zst                        Compress stdin (raw mode) to out.zst\n        t2sz - -o out.tar.zst                       Compress tar from stdin to out.tar.zst\n        t2sz -r - -o -                              Compress stdin to stdout (raw mode)\n\nOptions:\n        -l [1..22]         Set compression level, from 1 (lower) to 22 (highest). Default is 3.\n        -o FILENAME        Output file name. Use '-' to write to standard output.\n                           When reading from stdin ('-') and -o is omitted, output defaults to stdout.\n        -s SIZE            In raw mode: the exact size of each input block, except the last one.\n                           In tar mode: the minimum size of an input block, in bytes.\n                                        A block is composed by one or more whole files.\n                                        A file is never split unless -S is used.\n                                        If not specified one block will contain exactly one file, no matter the file size.\n                                        Each block is compressed to a zstd frame but if the archive has a lot of small files\n                                        having a file per block doesn't compress very well. With this you can set a trade off.\n                           The greater is SIZE the smaller will be the archive at the expense of the seek speed.\n                           SIZE may be followed by the following multiplicative suffixes:\n                               k/K/KiB = 1024\n                               M/MiB = 1024^2\n                               G/GiB = 1024^3\n                               kB/KB = 1000\n                               MB = 1000^2\n                               GB = 1000^3\n        -S SIZE            In raw mode: it is ignored.\n                           In tar mode: the maximum size of an input block, in bytes.\n                           Unlike -s this option may split big files in smaller chunks.\n                           Remember that each block is compressed independently and a small value here will result in a bigger archive.\n                           -S can be used together with -s but MUST be greater or equal to its value.\n                           If -S and -s are equal the input block will be of exactly that size, if there is enough input data.\n                           Like -s SIZE may be followed by one of the multiplicative suffixes described above.\n        -T [1..N]          Number of thread to spawn. It improves compression speed but cost more memory. Default is single thread.\n                           It requires libzstd \u003e= 1.5.0 or an older version compiler with ZSTD_MULTITHREAD.\n                           If `-s` or `-S` are too small it is possible that a lower number of threads will be used.\n        -r                 Raw mode or non-tar mode. Treat tar archives as regular files, without any special handling.\n        -j                 Do not generate a seek table.\n        -v                 Verbose. List the elements in the tar archive and their size.\n        -f                 Overwrite output without prompting.\n        -h                 Print this help.\n        -V                 Print the version.\n\n```\n\n## License\n\nSee LICENSE\n\n## Release\n\n### Debian-based\n\nDownload the latest stable source code or .deb from the [release page](https://github.com/martinellimarco/t2sz/releases/latest). This is the recommended version.\n\n### Arch-based\n\nCheck out [t2sz](https://aur.archlinux.org/packages/t2sz/) on AUR or `pamac build t2sz`\n\n### Snap\n\nFor your convenience you can install the latest release from the [snap store](https://snapcraft.io/t2sz) but beware that it is distributed in strict mode and it can access only your home directory by default.\n\nYou can add access to removable devices such as those stored in `/media` with `sudo snap connect t2sz:removable-media`.\n\nIf you want to give it access to every file you can install it with `--devmode`.\n\n[![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/t2sz)\n\n### Homebrew\n\nOn Linux and macOS you can install with [Homebrew](https://brew.sh/):\n\n```bash\nbrew tap martinellimarco/t2sz\nbrew install t2sz\n```\n\n## Testing\n\nThe project includes a comprehensive test suite covering round-trip correctness\n(compress → decompress → SHA-256 verify), memory safety (AddressSanitizer +\nUBSanitizer), and code coverage (LLVM).\n\nSee [TESTING.md](TESTING.md) for\nprerequisites, build configurations, and the full list of test cases.\n\n## Fuzzing\n\nThe project includes [libFuzzer](https://llvm.org/docs/LibFuzzer.html) harnesses\nfor fuzz-testing the tar header parser and the streaming compression paths.\n\nSee [FUZZING.md](FUZZING.md) for build instructions and usage.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinellimarco%2Ft2sz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinellimarco%2Ft2sz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinellimarco%2Ft2sz/lists"}