Skip to content

Instantly share code, notes, and snippets.

@GeorgeTR1
Last active September 15, 2026 01:00
Show Gist options
  • Select an option

  • Save GeorgeTR1/4912dc17d62cb07e319594de2b30fce6 to your computer and use it in GitHub Desktop.

Select an option

Save GeorgeTR1/4912dc17d62cb07e319594de2b30fce6 to your computer and use it in GitHub Desktop.
Safely extract tar files without polluting the current directory
#!/bin/sh
# usage: ./tarex.sh example.tar.gz
# will extract example.tar.gz, making sure it is always contained in a single
# directory in the current directory
# Keeps directory clean from "tar bombs" by creating a directory to extract the tar file into,
# and then only copying the results back to the current directory if there is only one file
# or directory, indicating that the results were contained in one directory
# tar file to extract
FILE=$1
# NAME becomes file name without extension
# exam.ple.tar.gz -> exam.ple
# exam.ple.tar -> exam.ple
NAME=${FILE%.*}
NAME=${NAME%.tar}
# random string of characters to avoid file name conflict,
# the chance that a file will be named this is astronomically low.
# I generated this with Python, it wasn't just me typing "randomly"
# Even if a malicious actor named a file this, it wouldn't do any harm,
# so no need to worry
RAND=gwrvegvusbqifcg
# create a directory with the same name as the .tar file, minus extensions
mkdir "$NAME"
# a uses the file extension to infer compression type (gz, bz2, xz, none, etc.)
# -C changes directory to the one we just created before extracting files
if tar xaf "$FILE" -C "$NAME"
then # tar command was successful
count=0 # represents number of files/directories in the directory we created
# (non-recursive)
for _ in "$NAME"/*; do # "_" is a garbage variable we discard names into,
# we only care if the loop runs more than once, indicating
# the output from tar wasn't contained in one directory
# (or wasn't just one file)
if [ $count = 1 ]; then
count=2
break
fi
count=1
done
# if the results were contained (as we would hope), we copy the directory that was
# extracted out of the container directory and into the current directory
if [ $count = 1 ]; then
# rename the container directory to the random string of letters to guarantee
# it has a different name than the directory that was extracted
# For example, it would be very typical that when you extract "example.tar.gz"
# you get a directory called "example" that contains all other files/directories
mv "$NAME" $RAND
mv $RAND/* ./
rmdir $RAND
fi
else
# if tar failed, remove the directory we created to clean up
rmdir "$NAME"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment