Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 

Repository files navigation

unzip-merge

Unzip and merge multiple zip files (e.g. Google Drive Takeout splits) into a single directory, and automatically fix garbled filenames produced by zips that don't set the UTF-8 flag (CP437 → UTF-8).

Why

Google Drive Takeout, and many Windows-created .zip archives, store filenames in CP437 instead of UTF-8. When extracted on macOS or Linux, non-ASCII names (Japanese, Chinese, Korean, accented characters, etc.) come out as mojibake. This script extracts all zips into one merged directory, then walks the tree and renames any entries whose names round-trip cleanly from CP437 back to UTF-8.

Platforms

Works on Linux, macOS, and Windows (via Git Bash, MSYS2, Cygwin, or WSL — any environment that gives you bash).

Requirements

  • bash
  • unzip
  • iconv (used for the encoding fix; supports CP437)
  • find, awk, df, stat (POSIX, pre-installed everywhere above)

All of these come pre-installed on a default macOS install, every common Linux distro, and inside Git Bash / MSYS2 / Cygwin / WSL on Windows. No Python required.

Usage

Run the script straight from GitHub — no clone, no install. cd into the directory that contains your *.zip files first.

# Extract every *.zip in the current directory into ./merged
curl -fsSL https://raw.githubusercontent.com/raftio/unzip-merge/master/unzip_merge.sh | bash

# Use a custom output directory
curl -fsSL https://raw.githubusercontent.com/raftio/unzip-merge/master/unzip_merge.sh | bash -s -- -o out

# Overwrite existing files in the output directory
curl -fsSL https://raw.githubusercontent.com/raftio/unzip-merge/master/unzip_merge.sh | bash -s -- -f

# Pass specific zips explicitly (instead of globbing *.zip)
curl -fsSL https://raw.githubusercontent.com/raftio/unzip-merge/master/unzip_merge.sh | bash -s -- a.zip b.zip c.zip

Anything after bash -s -- is forwarded to the script as arguments.

Or download once and reuse it:

curl -fsSLO https://raw.githubusercontent.com/raftio/unzip-merge/master/unzip_merge.sh
chmod +x unzip_merge.sh
./unzip_merge.sh -o out

Options

Flag Description
-o OUTPUT Output directory (default: ./merged)
-f Overwrite existing files (unzip -o)
-h Show help

By default, existing files are kept (unzip -n), so re-running the script is safe and idempotent.

What it does

  1. Collects the list of zip files (positional args, or *.zip in the current directory).
  2. Sums their sizes and warns if the destination has less than ~1.2× free space.
  3. Extracts each zip into the output directory in order.
  4. Walks the output tree (bottom-up via find -depth) and uses iconv to try UTF-8 → CP437 → UTF-8 on every entry name; if it round-trips cleanly, renames it — fixing mojibake from archives that lack the UTF-8 flag.

Install

chmod +x unzip_merge.sh

Optionally drop it on your PATH:

# Linux / macOS
ln -s "$PWD/unzip_merge.sh" /usr/local/bin/unzip-merge

On Windows, just call it from Git Bash / MSYS2 / WSL:

bash unzip_merge.sh -o merged

Tests

A self-contained test suite lives in tests/run_tests.sh. It uses only bash, zip, unzip, iconv, and find (no test framework, no external deps).

bash tests/run_tests.sh           # run all tests
bash tests/run_tests.sh -v        # show output of failing tests
bash tests/run_tests.sh -k encoding   # only tests whose name matches "encoding"

The suite covers: CLI flags (-h, -o, -f), error paths (no zips, missing zip), single/multiple zip merging, default skip-existing vs -f overwrite, explicit zip args, and the CP437→UTF-8 mojibake fix (top-level + nested directories, plus the no-op case for already-valid UTF-8 names).

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages