If an archive contains several files in the root directory, I'd like to create
a directory named after the file name (without extension). If an archive
contains just a directory, then I'd like to simply extract it. Assume I have
the following archive:

# file: withdir.zip
somedir/alpha
somedir/beta
somedir/gamma

If I extract it in the current directory I'd like to have it simply extracted
(unzip withdir.zip):

somedir/alpha
somedir/beta
somedir/gamma

Now assume the following archive:

# file: nodir.zip
alpha
beta
gamma

When I run unzip nodir.zip I end up cluttering the current directory
with the three files:

alpha
beta
gamma

I'd rather run unzip -d nodir nodir.zip:

nodir/alpha
nodir/beta
nodir/gamma

If I use nautilus and right click on “Extract Here”. It behaves exactly as it
should. But unfortunately I haven't found a command line switch for unzip or
7z which yield the same behaviour. How to achieve that? Are there other tools I can use instead
(no GUI)?

if it created only one file/dir, move it one level up and discard our directory

otherwise, attempt to strip the random string from the end of our temp directory.

This way, you can do:

unz unzip foo.zip
unz tar xf foo.tar.gz

It assumes that the last argument to the extracting command is the file to extract. It also assumes GNU tools for the -v options. On non-GNU systems, you can remove those and possibly do the logging by hand. mv -T is also GNU specific, and is to force mv to attempt do a rename only.

As unzip and 7z both have a switch to output to a given directory, you can create a simple script, that checks, how many files are in the root of the archive and then adds the switch if needed.

With 7z this is easier, as it has the -slt switch, which makes the output more machine-readable. For every file in the zip, the output will contain a Path = ... line. Files in the root should not contain any / in the value.

This script doesn't work as expected. It creates a directory withdir for the archive withdir.zip although it contains just one directory in the root because grep -c "Folder = -" returns 3.
–
MarcoFeb 7 '13 at 11:24

ah, Folder seems to be different for zip files. I'll look for a fix
–
crater2150Feb 7 '13 at 11:26

@Marco: I changed the script and tested it with zip files, it now only creates the folder when needed
–
crater2150Feb 7 '13 at 11:32