VMHeaven

Guides

How to extract tar.gz (and tar.xz, tar.bz2) files in Linux

Extract a tar.gz with tar -xzf, pick the target folder with -C, list the contents first and create archives yourself. Covers .tar.xz, .tar.bz2 and .zst.

Published ~9 min read

To extract a .tar.gz file in Linux, run tar -xzf file.tar.gz. It unpacks into the current directory; add -C /path to unpack somewhere else. Current GNU tar recognises the compression by itself, so tar -xf works for .tar.gz, .tar.xz, .tar.bz2 and .tar.zst alike. List the contents with tar -tzf before you extract anything you did not pack yourself.

the commands you will actually use
tar -xzf archive.tar.gz                    # extract here
tar -xzf archive.tar.gz -C /opt/app        # extract into /opt/app (must exist)
tar -tzf archive.tar.gz | head             # look inside first
tar -xf archive.tar.xz                     # any format: tar detects it
tar -czf backup.tar.gz mydir/              # create a tar.gz from a directory

What do the tar options mean?

Each letter is one option, and they can be bundled behind a single dash. The one rule that matters is that f takes the archive name, so it goes last in the bundle: -xzf archive.tar.gz works, while -xfz archive.tar.gz makes tar look for an archive called z. The old form without the dash, tar xzf, does the same.

tar options
-x          extract
-c          create
-t          list the contents
-f FILE     the archive to read or write
-z          gzip      (.tar.gz, .tgz)
-J          xz        (.tar.xz, .txz)
-j          bzip2     (.tar.bz2, .tbz2)
--zstd      zstd      (.tar.zst), needs the zstd program
-a          choose the compression from the file name (when creating)
-v          print each file name as it is processed
-C DIR      change to DIR first: extract into it, or create from it
-p          restore permissions exactly (the default when run as root)
-k          never overwrite files that already exist
--strip-components=N    drop the first N parts of every path

Automatic detection works when tar reads a file. When the archive comes through a pipe, name the compression yourself, as in curl -fL URL | tar -xzf -; without the z, GNU tar stops with “Archive is compressed. Use -z option”.

On Alpine Linux, tar is BusyBox’s compact version. It handles the everyday commands above but lacks several GNU options used further down, such as --skip-old-files and --keep-newer-files. apk add tar installs GNU tar.

How do I extract to a specific directory?

With -C. The target directory has to exist, so create it first:

extract somewhere else
mkdir -p ~/app
tar -xzf archive.tar.gz -C ~/app

# a system directory needs root
sudo mkdir -p /opt/app
sudo tar -xzf archive.tar.gz -C /opt/app

How do I see what’s inside before extracting?

Use -t instead of -x. Most archives put everything under one top-level folder, but some unpack dozens of files straight into whatever directory you are in. Checking the first lines tells you which kind you have:

list without extracting
tar -tzf archive.tar.gz | head          # first entries: one folder, or loose files?
tar -tzf archive.tar.gz | wc -l         # how many entries
tar -tvzf archive.tar.gz | head         # with permissions, owner, size and date

If the entries do not share a folder, extract into a fresh directory with -C rather than into your home directory or a web root.

How do I extract a single file or folder?

Name it after the archive, exactly as tar -t prints it, including a leading ./ if the listing shows one:

extract only part of an archive
tar -tzf site.tar.gz | grep wp-config               # find the exact path
tar -xzf site.tar.gz public_html/wp-config.php       # one file
tar -xzf site.tar.gz public_html/wp-content/uploads  # one folder, with everything in it
tar -xzf site.tar.gz --wildcards '*.sql'             # every file matching a pattern
tar -xzOf site.tar.gz public_html/.htaccess          # print to the screen instead

The file lands at its full path inside the archive, here public_html/wp-config.php under the current directory, not loose next to the archive.

How do I drop the top-level folder when extracting?

Add --strip-components=1. It removes the first part of every path, so the contents of the archive’s folder land directly in your target. The usual case is a download like WordPress, which wraps everything in a wordpress/ folder:

unpack the contents, not the wrapper folder
curl -fLO https://wordpress.org/latest.tar.gz
tar -tzf latest.tar.gz | head -3        # wordpress/, wordpress/index.php, ...
sudo mkdir -p /var/www/example.com
sudo tar -xzf latest.tar.gz -C /var/www/example.com --strip-components=1

How do I create a tar.gz archive?

With -c instead of -x, then the archive name, then what to pack. Use -C on this side too, so the archive stores example.com/... rather than the full path from /:

create archives
tar -czf site.tar.gz -C /var/www example.com

# with the date in the name, leaving out caches and logs
tar -czf "site-$(date +%F).tar.gz" --exclude='*/cache/*' --exclude='*.log' -C /var/www example.com

tar -cJf site.tar.xz -C /var/www example.com      # xz: smaller, slower
tar -caf site.tar.zst -C /var/www example.com     # format from the suffix (zstd installed)
  • Put --exclude before the paths. Current GNU tar warns about options that come after the files to pack, and they may not apply.
  • Permissions and owners are always stored. They are restored when you extract as root, or with -p for permissions as a normal user. Pack as root (sudo tar) if some files are readable only by root, or tar skips them with “Permission denied”.
  • Do not archive a running database’s files. The copy can be inconsistent. Dump it with mysqldump or pg_dump and pack the dump.

Which compression format should I use?

  • gzip (.tar.gz) is fast and readable everywhere, from any Linux to Windows and macOS. The safe default, especially for files you hand to someone else. With pigz installed, tar -I pigz -cf archive.tar.gz dir/ compresses on every core.
  • xz (.tar.xz) usually makes noticeably smaller files, especially for source code and text, but is much slower to create. Common for software releases.
  • bzip2 (.tar.bz2) is the older middle ground and today mostly something you unpack, not create. Minimal images may lack it: “bzip2: Cannot exec” means sudo apt install bzip2.
  • zstd (.tar.zst) is fast to compress and very fast to unpack, with sizes close to xz at higher levels. It needs GNU tar 1.31 or newer, which every current distribution has, and the zstd program (sudo apt install zstd or sudo dnf install zstd). Good for your own backups.

Why does tar say “gzip: stdin: not in gzip format”?

the error
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now

The file is not gzip-compressed, whatever its name says. Either it is a plain tar archive with the wrong suffix, or what you downloaded is not the archive at all, but an HTML error page, a login page or a redirect saved under the archive’s name. Ask file what it really is:

what is this file?
file archive.tar.gz
# POSIX tar archive               -> not compressed at all: tar -xf archive.tar.gz
# XZ compressed data              -> wrong suffix: tar -xf archive.tar.gz
# Zip archive data                -> a ZIP with the wrong name: unzip archive.tar.gz
# HTML document, ASCII text       -> you saved a web page, not the archive
head -c 300 archive.tar.gz        # shows the HTML, if that is what it is

For a saved web page, download again with curl -fL: -L follows redirects, which release downloads on GitHub and many mirrors use, and -f makes curl fail on an HTTP error instead of saving the error page. Compare the checksum if the project publishes one:

download it properly
curl -fL -o archive.tar.gz 'https://example.com/releases/archive.tar.gz'
sha256sum archive.tar.gz          # compare with the published value

wget -O archive.tar.gz URL works too: it follows redirects and does not save error pages by default. If either tool is missing, see wget: command not found or curl: command not found. Related messages: “Unexpected EOF in archive” means the file is cut off, so download it again. “This does not look like a tar archive” often means a single compressed file such as dump.sql.gz, which you unpack with gunzip dump.sql.gz, or a ZIP file with the wrong name. For real .zip files, see unzip: command not found.

Why does tar say “Cannot open: Permission denied”?

the error
tar: example.com/index.php: Cannot open: Permission denied
tar: Exiting with failure status due to previous errors

When extracting, your user may not write into the target directory: extract into a directory you own, or use sudo for system paths such as /var/www or /opt. When creating, your user cannot read some of the files: pack with sudo. Extracting as root also restores the original owners, and an owner that does not exist on the new server shows up as a bare number. Add --no-same-owner and chown the result yourself, as in sudo chown -R www-data:www-data /var/www/example.com.

Does tar overwrite existing files?

Yes, silently. A file in the archive replaces a file of the same name on disk, and files that are only on disk stay where they are. To protect what is already there:

extract without overwriting
tar -xzkf archive.tar.gz                    # -k: error for every file that exists
tar -xzf archive.tar.gz --skip-old-files    # skip existing files quietly
tar -xzf archive.tar.gz --keep-newer-files  # keep files on disk that are newer

# the careful way: extract into an empty directory and compare
mkdir /tmp/check && tar -xzf archive.tar.gz -C /tmp/check
diff -rq /tmp/check/example.com /var/www/example.com

How do I extract a tar.gz on Windows?

Windows 10 (version 1803 and later), Windows 11 and Windows Server 2019 and later include tar.exe, so the same command works in PowerShell or Command Prompt. It detects the compression on its own. Windows 11 also opens .tar.gz in File Explorer, and 7-Zip works everywhere, in two steps: first the .gz, then the .tar.

PowerShell · Command Prompt
tar -xf archive.tar.gz
tar -xf archive.tar.gz -C C:\Temp\out       # the folder must exist
tar -czf backup.tar.gz myfolder

How do I pack a website to move it to a VPS?

Pack it on the old server, copy it over, and unpack it on the new one. A tarball keeps file permissions intact, which a ZIP export from a hosting panel often does not:

move a site with tar
# on the old server
tar -czf site.tar.gz -C /home/user public_html

# copy it to the new VPS
scp site.tar.gz admin@203.0.113.10:/tmp/

# on the new VPS
sudo mkdir -p /var/www/example.com
sudo tar -xzf /tmp/site.tar.gz -C /var/www/example.com --strip-components=1

# or in one go over SSH, without a temporary file
tar -czf - -C /home/user public_html | ssh admin@203.0.113.10 'mkdir -p ~/site && tar -xzf - -C ~/site'

The files are only part of a move; databases, DNS and mail are the other part, and the whole order of work is in moving from shared hosting to a VPS. If the new home is a VMHeaven Standard KVM server, you have full root and can unpack straight into the web root.

Frequently asked

What is the difference between .tar and .tar.gz?

A .tar file bundles many files and folders into one archive, with their paths, permissions and owners, but without compression. A .tar.gz (or .tgz) is that same archive compressed with gzip, so it is smaller. Extract a .tar with tar -xf file.tar and a .tar.gz with tar -xzf file.tar.gz; on current GNU tar, tar -xf works for both.

How do I extract a tar.gz file on Windows?

Windows 10 (version 1803 and later), Windows 11 and Windows Server 2019 and later include tar.exe. Open PowerShell or Command Prompt in the folder and run tar -xf file.tar.gz, adding -C followed by an existing folder to extract somewhere else. Windows 11 also opens .tar.gz files in File Explorer, and 7-Zip can extract them in two steps.

Does tar overwrite existing files when extracting?

Yes. A file in the archive silently replaces a file with the same name on disk; files that exist only on disk are left alone. Use -k (--keep-old-files) to get an error instead, --skip-old-files to skip existing files quietly, or extract into an empty directory first and compare with diff -rq.

Can I extract a tar.gz without root?

Yes, into any directory your user can write to, such as your home directory or /tmp. The extracted files belong to you, and permissions follow your umask unless you add -p. You need sudo only to write into system directories such as /var/www or /opt, or to restore the original owners recorded in the archive.

Related articles

All guides