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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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 -j omeka-1.5.1.zip -d omeka cd omeka ll
Method 2
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
Method 3
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.
Method 4
Solution: unzip through a temporary symlink
In my case I wanted to overwrite a directory full of existing files with the content of a zip, without extracting the full zip first.
This solution is simple, does not require FUSE, only requires possibility of creating a symlink to the target directory.
How to do it
Assuming you know the extra directory, in you case omeka-1.5.1, you can do this:
mkdir omeka
ln -s . omeka/omeka-1.5.1 # create a symlink that redirects output
unzip omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remove symlink
rmdir omeka
unzip will try to unzip to omeka-1.5.1 which is actually a symlink to containing dir. As a result, files will land in omeka directly.
Possible variants
You can imagine variants to redirect one or more parts of a depeer hierarchy.
ln -s ../myfoo omeka/omeka-1.5.1/foo
ln -s ../../mybarxyzzy omeka/omeka-1.5.1/subdir/bar
You can also use this trick if the target filesystem does not allow symlinks:
cd /tmp # or any dir where you can create a symlink
mkdir omeka
ln -s /path/to/target/even/if/no/symlink/possible omeka/omeka-1.5.1
unzip /path/to/omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remove symlink
rmdir omeka
Conclusion
This solution is kind of a hack but works very well.
Idea for improvement of unzip
It would be desirable to have an option to unzip, like patch --strip=number (or -pnumber) that chops number path components at beginning (ref. Comparing and Merging Files: patch Directories).
Method 5
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.
Method 6
Most likely you want to run unzip with the -j option, as in:
unzip -j files.zip -d ./output/
But you might be surprised by its behavior:
-j junk paths. The archive’s directory structure is not recreated; all files are deposited in the extraction directory (by
default, the current one).
If you extract files.zip in output directory ./output and you get this as a result:
./output/files/subfolder1/f1 ./output/files/subfolder1/f2
then the -j option will give you this (all paths striped):
./output/f1 ./output/f2
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0