0

On several occasions, say I have a.zip, which unzips into a/* itself.

However, often there are zip files which spill all their contents into the current directory. This requires me to manually create a director a and unzip into it.

But if as a policy I always create a directory, and the zip turns out to be of the first kind, my structure looks like a/a/* which is not ideal.

Is there a way to unzip a.zip into a/* irrespective of its type among the two types which I described above?

2 Answers 2

2

Try this:

archive="archive.zip"
has_parent=$(unzip -l "$archive" | tail -n+4 | head -n-2 | awk '{split($NF,a,"/");print a[1]}' | sort -u | wc -l)
if test "$has_parent" -eq 1; then
  unzip $archive
else
  dir="./$(basename ${archive%%.zip})"
  mkdir "$dir"
  unzip -d "$dir" $archive
fi

If using zipinfo you can squeeze $has_parent line to this:

has_parent=$(zipinfo -1 "$archive" | awk '{split($NF,a,"/");print a[1]}' | sort -u | wc -l)

Idea is simple - if there are several files on the root level of the archive it obviously will trash your current directory if you unpack it, therefore you must create a parent directory beforehand and unpack files in there. Otherwise if all the files in the archive have the same parent then it's ok to unpack in the current dir.

1

Use zipinfo for displaying, zip contents.:

$ zipinfo -1 a.zip

Though, this probably doesn't answer your question if you are looking for an automation answer.

Edit: What you could do is check each line of output from zipinfo for a forward slash character. If there is a line missing the character, you know that it is located at the root of the zip file.

Unfortunately, I can't think of exactly how to do this of the top of my head. Not sure if it will work, but here is an untested command:

$ MKROOT=0
$ for X in $(zipinfo -1 a.zip); do $(echo "${X}" | grep "/"); if test "$?" -gt "0"; then MKROOT=1; fi; done
$ if test "${MKROOT}" -gt "0"; then mkdir "a"; cd "a"; unzip "../a.zip"; else unzip "a.zip"; fi

Edit: Mark Perryman's suggestion is probably better. I just realized that my command checks if files are contained in sub-folders, but it doesn't check if all are contained under the same root folder.

1
  • 1
    zipinfo -1 a.zip | sed -r 's#([^/]+/).*#\1#' | sort -u | wc -l will output 1 if all paths have the same leading directory. Commented Nov 28, 2017 at 10:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .