24

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

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

ls 
myArchive123.tar.gz
helloWorld 

I would like the output to be the same name 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. 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 mean time I hacked myself a script that seems to get the job done. (see my posted answer below). If it can be improved, please feel free to post comments/additional answers. The main thing is that it should be packagable into a one-liner like:

extract <file>
9
  • 1
    Does the archive always contain exactly one folder? Apr 23, 2015 at 14:24
  • 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. 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. Apr 23, 2015 at 14:50
  • Will the archive ever contain more than one folder at the top level? Apr 23, 2015 at 15:02

5 Answers 5

12

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.

11

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> 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 Apr 23, 2015 at 16:21
  • In the script above I strip the extension and strip it further if I find a 'tar'. 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? Apr 23, 2015 at 16:32
  • Good stuff. This works and is shorter than the script I wrote. Nice! Apr 23, 2015 at 20:18
4
$ 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).

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 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? Apr 23, 2015 at 14:22
  • You're correct. It's only one possible solution as I wrote here...
    – svq
    Apr 23, 2015 at 14:23
  • is there any difference between that and --strip-compoments=0 myArchive123? 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
    Apr 23, 2015 at 14:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.