Skip to content
Back to Blog
how-to-convert

How to Convert ZIP to TAR (Linux Server Migrations)

2026-05-17 9 min read

Why ZIP and TAR Exist in Different Worlds

ZIP was designed in 1989 by Phil Katz primarily for DOS and Windows environments. It bundles compression and archiving into a single step, stores files individually (so you can extract one file without decompressing the rest), and carries Windows-style metadata like file attributes. TAR — short for Tape ARchive — was built for Unix systems and does something fundamentally different: it concatenates files into a single stream without compressing anything by default. Compression is layered on top separately, usually via gzip (.tar.gz) or bzip2 (.tar.bz2). This distinction matters enormously during Linux server migrations. When you receive a ZIP archive from a Windows developer or a hosting panel backup and need to deploy it on a Linux server, you often run into permission problems, symlink breakage, and metadata loss. TAR preserves Unix file permissions (chmod values like 755 or 644), ownership (uid/gid), symlinks, and hard links in a way that ZIP simply was not designed to handle reliably across platforms. For example, a WordPress installation zipped on Windows might lose the execute bit on wp-cron.php or flatten symlinks entirely. Repackaging that archive as a .tar.gz before deploying to an Apache or Nginx server avoids those headaches. The conversion from ZIP to TAR is not just a format preference — it is often a prerequisite for a clean migration.

The Fastest Method: CocoConvert for Small to Medium Archives

For archives under 2 GB, the quickest path is to use an online tool. CocoConvert's [ZIP to TAR converter](/convert/zip-to-tar) handles the extraction and repackaging in the cloud, so you do not need to install anything locally or provision a conversion environment on your server. The process is straightforward: 1. Navigate to [cocoConvert.com/convert/zip-to-tar](/convert/zip-to-tar). 2. Click 'Choose File' or drag your .zip file into the upload area. 3. Select your output format — plain .tar, .tar.gz, or .tar.bz2 depending on your use case. 4. Click 'Convert' and wait. A 500 MB ZIP typically processes in 30 to 90 seconds depending on server load. 5. Download the resulting TAR file directly to your machine or copy the download link to pull it straight onto your server with wget. A practical note on format choice: if you are migrating to a server with limited disk space, pick .tar.gz — it usually achieves 60–70% compression on text-heavy codebases. If you need faster decompression at the cost of slightly larger files, .tar.bz2 is slower to create but decompresses well on older hardware. Be honest about what CocoConvert cannot do here: it is not the right tool for archives over 2 GB, for archives containing encrypted ZIP entries, or for situations where you need to preserve very specific Unix ACLs (Access Control Lists) set inside the original ZIP. For those cases, you need the command-line approach described below.

Command-Line Conversion on Linux: The Reliable Way for Large Archives

If your archive is large, lives on a remote server already, or contains complex permission requirements, the command line gives you full control. You need two standard utilities: unzip and tar. Both are available on virtually every Linux distribution. First, verify they are installed: ``` which unzip tar ``` On Debian/Ubuntu, install them with: sudo apt install unzip tar On RHEL/CentOS/AlmaLinux: sudo dnf install unzip tar The conversion is a two-step process. Step one extracts the ZIP: ``` unzip archive.zip -d ./extracted_content ``` The -d flag specifies the destination directory. Without it, unzip dumps everything into the current directory, which gets messy fast. Step two repackages as TAR: ``` tar -czf archive.tar.gz -C ./extracted_content . ``` Breaking down the flags: -c creates a new archive, -z applies gzip compression, -f specifies the output filename, and -C changes into the specified directory before archiving. The trailing dot means 'archive everything in this directory' — this prevents the archive from containing an extra nested folder level, which is a common mistake that causes deployment paths to break. If you want .tar.bz2 instead, replace -z with -j: ``` tar -cjf archive.tar.bz2 -C ./extracted_content . ``` For a plain uncompressed TAR (useful when the files are already compressed images or binaries): ``` tar -cf archive.tar -C ./extracted_content . ``` After conversion, verify the archive integrity before deleting the extracted directory: ``` tar -tzf archive.tar.gz | head -20 ``` This lists the first 20 entries. If you see the expected file structure, the archive is intact.

Handling File Permissions and Ownership During Migration

This is where most ZIP-to-TAR migrations go wrong. ZIP stores permissions as a 16-bit external attribute field, but this field is not consistently written or read across platforms. A ZIP created on macOS may encode permissions correctly; one created by Windows Explorer almost certainly will not. When you extract a ZIP on Linux with unzip, the tool attempts to reconstruct permissions but often falls back to defaults — typically 644 for files and 755 for directories, modified by your current umask. If your umask is 022 (the standard), files come out as 644 and directories as 755. That is fine for most web assets but breaks scripts that need to be executable. Before creating your TAR, audit and fix permissions manually: ``` # Set all files to 644 find ./extracted_content -type f -exec chmod 644 {} \; # Set all directories to 755 find ./extracted_content -type d -exec chmod 755 {} \; # Make shell scripts executable find ./extracted_content -name '*.sh' -exec chmod 755 {} \; ``` Ownership is a separate concern. If you are migrating a web application, the files likely need to be owned by www-data (Debian/Ubuntu) or nginx or apache (RHEL-based). Set this before creating the TAR if the archive will be deployed by a script that expects specific ownership: ``` sudo chown -R www-data:www-data ./extracted_content ``` TAR preserves whatever ownership and permissions exist at archive creation time, so getting them right before running tar -czf means the deployment target just needs to extract the archive — no post-deployment chmod scripts required. This is a significant operational advantage over ZIP for automated deployments.

Automating ZIP-to-TAR Conversion in Migration Scripts

When you are migrating multiple sites or running this process repeatedly — for example, converting weekly ZIP backups from a cPanel host into TAR archives for a new server — automation saves significant time and reduces human error. Here is a practical shell script that processes every ZIP file in a directory: ```bash #!/bin/bash SOURCE_DIR="/srv/backups/zip" DEST_DIR="/srv/backups/tar" TMP_DIR="/tmp/zip_conversion" mkdir -p "$DEST_DIR" "$TMP_DIR" for zipfile in "$SOURCE_DIR"/*.zip; do basename=$(basename "$zipfile" .zip) extract_path="$TMP_DIR/$basename" echo "Processing: $basename" mkdir -p "$extract_path" unzip -q "$zipfile" -d "$extract_path" # Fix permissions find "$extract_path" -type f -exec chmod 644 {} \; find "$extract_path" -type d -exec chmod 755 {} \; tar -czf "$DEST_DIR/${basename}.tar.gz" -C "$extract_path" . # Verify before cleanup if tar -tzf "$DEST_DIR/${basename}.tar.gz" > /dev/null 2>&1; then echo "Success: ${basename}.tar.gz" rm -rf "$extract_path" else echo "ERROR: Conversion failed for $basename" >&2 fi done rm -rf "$TMP_DIR" ``` Save this as convert_zips.sh, make it executable with chmod 755 convert_zips.sh, and run it with ./convert_zips.sh. The script validates each TAR before deleting the temporary extraction directory, which prevents silent data loss. For scheduled conversions, add it to cron: 0 2 * * * /srv/scripts/convert_zips.sh >> /var/log/zip_conversion.log 2>&1 runs the script at 2 AM daily with full logging.

Common Errors and How to Fix Them

Even straightforward conversions hit snags. Here are the most common problems encountered during ZIP-to-TAR migrations and their solutions. **'End-of-central-directory signature not found'** — This means the ZIP file is corrupted or was not fully downloaded. Verify the file size matches what the source reports, and re-download. You can also attempt repair with: zip -FF corrupted.zip --out repaired.zip **'Cannot allocate memory' during unzip** — Large archives with millions of small files exhaust the file descriptor table. Increase the limit for your session: ulimit -n 65536, then retry. **Symlinks missing in the TAR** — If unzip was run without the -X flag on some older versions, symlinks get extracted as regular files containing the link target path as text. Check your unzip version (unzip -v) and upgrade if it is below 6.0. Alternatively, use Python's zipfile module which handles symlinks more reliably: python3 -c "import zipfile; zipfile.ZipFile('archive.zip').extractall('extracted/')". **Filenames with spaces breaking tar** — If extracted filenames contain spaces, the find command in permission-fixing scripts can fail. Use find's -print0 and xargs -0 combination: find ./extracted_content -type f -print0 | xargs -0 chmod 644 **Archive too large for /tmp** — The default /tmp is often a tmpfs mount limited to half of RAM. Redirect temporary extraction to a disk-backed location: export TMPDIR=/var/tmp before running unzip, or specify the extraction directory explicitly as shown in the script above. **CocoConvert timeout on large files** — Files above 2 GB will time out on the web interface. This is a genuine limitation of browser-based tools; switch to the command-line method for anything larger.

Choosing the Right TAR Compression for Your Server Environment

Not all TAR archives are equal, and the compression choice affects both the migration process and ongoing server operations. Here is a practical breakdown. **.tar.gz (gzip)** — The default choice for most migrations. Compression ratio is typically 3:1 to 5:1 for source code and text files. Decompression is fast — a 1 GB .tar.gz extracts in roughly 15 seconds on a modern VPS. Supported everywhere without additional packages. Use this unless you have a specific reason not to. **.tar.bz2 (bzip2)** — About 10–15% better compression than gzip on typical web application files, but 3–4x slower to compress. Decompression is also slower. Worth using if the archive will be stored long-term and bandwidth or storage is expensive, but not ideal for frequent deployments. **.tar.xz (xz/LZMA)** — Best compression ratio, often 20–30% smaller than gzip on source code. Decompression is slow and memory-intensive — a 500 MB .tar.xz can require 700 MB of RAM to decompress. Avoid this for migration archives that will be extracted on resource-constrained servers. **.tar (no compression)** — Useful when the contents are already compressed (JPEG images, MP4 videos, pre-compressed database dumps). Adding gzip to an already-compressed file wastes CPU time and adds negligible size reduction. For most Linux server migrations involving PHP applications, Node.js projects, or Python codebases, .tar.gz is the right answer. It is what most deployment tools (Capistrano, Deployer, Ansible's unarchive module) expect by default, and it strikes the best balance between compression speed, decompression speed, and compatibility. If you want to convert your ZIP archive quickly without configuring any of this locally, CocoConvert's [ZIP to TAR converter](/convert/zip-to-tar) lets you choose between .tar, .tar.gz, and .tar.bz2 before downloading — a reasonable middle ground for one-off migrations where setting up a full command-line workflow is not worth the time.

Ready to convert?

Try it now — fast, secure, and private.

Convert Now →