Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Depending on how a zip file is created, sometimes it will extract all of the files directly, and sometimes it will extract the files into a subdirectory.

If the latter is true, how can I force the unzip command to "ignore" that first level directory?

Example:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
mkdir omeka
unzip omeka-1.5.1.zip -d omeka/
cd omeka/
ll

What I'm getting is /tmp/omeka/omeka-1.5.1/:

total 12
drwxr-xr-x 3 root root 4096 2012-05-08 18:44 ./
drwxrwxrwt 6 root root 4096 2012-05-08 18:44 ../
drwxr-xr-x 5 root root 4096 2012-04-20 14:54 omeka-1.5.1/

What I want is of the files extracted to /tmp/omeka/, (one level up and no version number included in the directory structure)

/tmp/omeka/(files)

I know I can use the -j option to "junk paths" but I want to keep the subdirectory structure, just not the top level directory structure. How can I do this?

share|improve this question
    
ps: I'm aware that I can extract and then mv the files, but I wanted to see if there was a way to do this straight away from the unzip command –  cwd May 8 '12 at 18:55
    
I'm not aware of one. But if the filename always matches (apart from the extension) the directory name, it's pretty straightforward to script the rename of the extracted dir. –  Mat May 8 '12 at 19:07
3  
I see what you're trying to do, but I wouldn't recommend it. Stripping the version number from your project sources is a bad idea; you should just extract normally and use a ln -s if you want a shorter name without version information. That way you always know what version you are running and can easily update to a new version by switching the link. –  Burton Samograd May 8 '12 at 19:38
    
@BurtonSamograd - that would be ideal, but I'm still curious if there is an effective way to do this because some software, take Wordpress as an example, puts every version inside a /wordpress/ directory (no version number) inside the zip file. It is indeed fine to unzip and then mv but having no control of this and having to do it in two steps has always gotten on my nerves a little. Fortunately Wordpress also comes in a .tar.gz flavor :) –  cwd May 9 '12 at 2:01
    
Try cd /tmp/omeka && ln -s -T . omeka-1.5.1 –  James Youngman May 9 '12 at 22:39

4 Answers 4

up vote 3 down vote accepted

Use a FUSE filesystem that allows you to browse archives like directories, such as AVFS. Use cp to extract the files to the directory of your choice.

mountavfs
cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/omeka-1.5.1 omeka

Since we're assuming that there is a single toplevel directory in the archive, you can shorten this to

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka
share|improve this answer
    
@Giles you are the expert who comes and answers all the questions nobody else can answer, so I guess this is truly the only way to do this. I was hoping unzip had some magic to do this, such as specifying the files to be extracted like */*, that I could use without installing another utility, but I guess not. Thanks. +1 –  cwd May 9 '12 at 2:05

If your zip file contains no directory structure or you do not need to preserve it, you can use this:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip omeka-1.5.1.zip -j -d omeka
cd omeka
ll
share|improve this answer
    
+1 for the -j option. –  Ricardo Dec 13 '13 at 11:57

This script is not robust, but works in the simple cases:

...
dest=omeka
unzip omeka-1.5.1.zip -d $dest/

if [ `ls $dest | wc -l` == 1 ]; then
  subdir=`ls $dest`
  mv $dest/$subdir/* $dest/
  rmdir $dest/$subdir
fi

It just checks to see if there is exactly one subdirectory, and if so, moves everything up out of it then deletes it.

share|improve this answer

I've just registered today, so I can't upvote @SteveBennet answer and can't add a comment there.

Based on his answer I created a recursive function like this:

...

shopt -s dotglob # To include hidden files in the move command

function moveSub {
  local dest=$1
  if [ `ls $dest | wc -l` == 1 ]; then
    local subdir=`ls $dest`
    moveSub "$dest/$subdir"
    mv $dest/$subdir/* $dest/
    rmdir $dest/$subdir
  fi
}

moveSub "$dest"

Just like @SteveBennet said: this script is not robust, but works in the simple cases.

Hope it's useful.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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