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.
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 directoryWhat 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.
-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 pathAutomatic 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:
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/appHow 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:
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 dateIf 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:
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 insteadThe 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:
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=1How 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 /:
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
--excludebefore 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
-pfor 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
mysqldumporpg_dumpand 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
pigzinstalled,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
zstdprogram (sudo apt install zstdorsudo dnf install zstd). Good for your own backups.
Why does tar say “gzip: stdin: not in gzip format”?
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting nowThe 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:
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 isFor 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:
curl -fL -o archive.tar.gz 'https://example.com/releases/archive.tar.gz'
sha256sum archive.tar.gz # compare with the published valuewget -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”?
tar: example.com/index.php: Cannot open: Permission denied
tar: Exiting with failure status due to previous errorsWhen 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:
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.comHow 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.
tar -xf archive.tar.gz
tar -xf archive.tar.gz -C C:\Temp\out # the folder must exist
tar -czf backup.tar.gz myfolderHow 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:
# 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.