18

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>
  • 1
    Does the archive always contain exactly one folder? – Mark Plotnick Apr 23 '15 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. – Leo Ufimtsev Apr 23 '15 at 14:49
  • In the mean time I pieced together a script (see below). I can accept the answer only in 2 days thou. – Leo Ufimtsev Apr 23 '15 at 14:50
  • Will the archive ever contain more than one folder at the top level? – Mark Plotnick Apr 23 '15 at 15:02
10

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
  • This is close to what I want, with exception that I'd like to be able to package it into something like: extract <file> – Leo Ufimtsev Apr 23 '15 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 – Leo Ufimtsev Apr 23 '15 at 16:21
  • In the script above I strip the extension and strip it further if I find a 'tar'. – Leo Ufimtsev Apr 23 '15 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? – Leo Ufimtsev Apr 23 '15 at 16:32
  • Good stuff. This works and is shorter than the script I wrote. Nice! – Leo Ufimtsev Apr 23 '15 at 20:18
7

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/"
  • 1
    but this pre-supposes that you know what's inside the archive – Leo Ufimtsev Apr 23 '15 at 14:22
  • e.g how would I turn this into a one-line script without knowing what's inside the archive? – Leo Ufimtsev Apr 23 '15 at 14:22
  • You're correct. It's only one possible solution as I wrote here... – svq Apr 23 '15 at 14:23
  • is there any difference between that and --strip-compoments=0 myArchive123? – Leo Ufimtsev Apr 23 '15 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 '15 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.