31

I have a zipped file like myArchive123.tar.gz. Inside, it contains a folder like helloWorld

If I extract it with tar -xf myArchive123.tar.gz, I get the helloWorld folder:

ls 
myArchive123.tar.gz
helloWorld 

I want the output to be the same as the file name minus the .tar.gz extension. I.e.:

tar <magic paramaters> myArchive123.tar.gz 
ls 
 myArchive123.tar.gz
 myArchive123
cd myArchive123
ls 
  helloWorld

Can this be done?

  • I never know what's inside the archive. It could be a folder, could be many files.
  • I'd be ok with using another tool if tar can't do it.
  • I'd be ok with a longer form that can be turned into a script

EDIT
In the meantime, I wrote myself a script that seems to get the job done (see my posted answer below). The main thing is that it should be packageable into a one-liner like:

extract <file>
9
  • 1
    Does the archive always contain exactly one folder? Commented Apr 23, 2015 at 14:24
  • See Create directory if zip archive contains several files
    – Marco
    Commented Apr 23, 2015 at 14:47
  • I don't know what's inside it at extraction time. This shouldn't depend on what's inside the archive either. If it's a folder, extract the folder in there. if it's a file, extract all files. Commented Apr 23, 2015 at 14:49
  • In the mean time I pieced together a script (see below). I can accept the answer only in 2 days thou. Commented Apr 23, 2015 at 14:50
  • Will the archive ever contain more than one folder at the top level? Commented Apr 23, 2015 at 15:02

5 Answers 5

18
$ tar -xf myArchive123.tar.gz --one-top-level

--one-top-level[=DIR]
Extract all files into DIR, or, if used without argument, into a subdirectory named by the base name of the archive (minus standard compression suffixes recognizable by --auto-compress).

14

With gnu tar, you could use --xform (or --transform) to prepend /prefix/ to each file name:

tar -xf myArchive.tar.gz --xform='s|^|myArchive/|S'

note there's no leading / in prefix/ and the sed expression ends with S to exclude symbolic link targets from file name transformations.
To test it (dry-run):

tar -tf myArchive.tar.gz --xform='s|^|myArchive/|S' --verbose --show-transformed-names

To get you started, here's a very simplistic script that you could invoke as extract <file>:

STRIP=${1%.*}                                #strip last suffix
NAME=${STRIP%.tar}                           #strip .tar suffix, if present
tar -xf "$1" --xform="s|^|$NAME/|S"          #run command
5
  • This is close to what I want, with exception that I'd like to be able to package it into something like: extract <file> Commented Apr 23, 2015 at 16:08
  • This is buggy, it stops at first dot. E.g I have a file like this: eclipse-SDK-4.5M6-linux-gtk-x86_64.tar.gz I expect an output without the .tar.gz, but I get eclipse-sdk-4 Commented Apr 23, 2015 at 16:21
  • In the script above I strip the extension and strip it further if I find a 'tar'. Commented Apr 23, 2015 at 16:22
  • In general, with many types of archives. I was hoping for a quick one-liner, I thought maybe I was missing some argument flag. But it seems that there is no trivial solution to this? Commented Apr 23, 2015 at 16:32
  • Good stuff. This works and is shorter than the script I wrote. Nice! Commented Apr 23, 2015 at 20:18
14

Well, you could do it in a couple of steps at least. If you did

mkdir <archive name>
tar -xf <archive name>.tar.gz --strip-components=1 -C <archive name>

that would accomplish the task, though there may be a more compact answer out there yet.

3

Edit

The accepted answer is shorter than the below. (do the same thing, but shorter is usually better).


I eventually hacked myself a script for the task at hand. it works with .tar .tar.gz and .gz

#!/bin/sh
#usage:
# nameOfScript myArchive.tar.gz
# nameOfScript myArchive.gz
# nameOfScript myArchive.tar
#
# Result:
# myArchive   //folder
fileName="${1%.*}" #extracted filename

#handle the case of archive.tar.gz
trailingExtension="${fileName##*.}"
if [ "$trailingExtension" == "tar" ]  
then
    fileName="${fileName%.*}"  #remove trailing  tar.
fi

mkdir "$fileName"
tar -xf "$1" --strip-components=0 -C "$fileName"

Usage:

   nameOfScript archive.tar.gz 
   ls 
    archive
   cd archive 
   ls 
    <archive content>

Note, this solution is capable of dots in a file name. E.g Eclipse-4.5M-SDK.tar.gz.

I keep the script in my git repo. For the latest version, see: https://github.com/LeoUfimtsev/ldts/blob/master/pathscripts/leo-tar-here

2

One more possible solution is using --transform option:

tar -xzf ARCHIVE_NAME.tgz --transform="s/OLD_DIR_NAME/ARCHIVE_NAME/"

With your files:

tar -xzf myArchive123.tar.gz --transform="s/helloWorld/myArchive123/"
6
  • 1
    but this pre-supposes that you know what's inside the archive Commented Apr 23, 2015 at 14:22
  • e.g how would I turn this into a one-line script without knowing what's inside the archive? Commented Apr 23, 2015 at 14:22
  • You're correct. It's only one possible solution as I wrote here...
    – svq
    Commented Apr 23, 2015 at 14:23
  • is there any difference between that and --strip-compoments=0 myArchive123? Commented Apr 23, 2015 at 14:36
  • 1
    And --strip-components=0 simply removes the first directory name from the path and with -C option stores de-archived files into the new directory.
    – svq
    Commented Apr 23, 2015 at 14:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .