5

This question already has an answer here:

How to unzip a file (ex: foo.zip) to a folder with the same name (foo/)?

Basically, I want to create an alias of unzip that unzips files into a folder with the same name (instead of the current folder). That's how Mac's unzip utility works and I want to do the same in CLI.

marked as duplicate by Christopher, Kusalananda, Rui F Ribeiro, Fabby, Anthony Geoghegan Dec 18 '18 at 0:45

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • @Christopher I don't see how it's a duplicate. Can you find an answer to my question in that question? – Emanuil Rusev Dec 17 '18 at 17:09
  • 1
    The accepted anwer answers your question: unzip -d foo foo.zip. – Fabby Dec 18 '18 at 0:28
  • 1
    @Fabby, no it doesn't, I need a dynamic solution that won't require adding the name of the target folder. I believe the second paragraph makes this very clear. – Emanuil Rusev Dec 18 '18 at 9:32
  • It seems to me that another answer there, by n.st does what you want? – Jeff Schaller Mar 6 at 15:47
6

I use unar for this; by default, if an archive contains more than one top-level file or directory, it creates a directory to store the extracted contents, named after the archive in the way you describe:

unar foo.zip

You can force the creation of a directory in all cases with the -d option:

unar -d foo.zip

Alternatively, a function can do this with unzip:

unzd() {
    if [[ $# != 1 ]]; then echo I need a single argument, the name of the archive to extract; return 1; fi
    target="${1%.zip}"
    unzip "$1" -d "${target##*/}"
}

The

target=${1%.zip}

line removes the .zip extension, with no regard for anything else (so foo.zip becomes foo, and ~/foo.zip becomes ~/foo). The

${target##*/}

expansion removes anything up to the last /, so ~/foo becomes foo. This means that the function extracts any .zip file to a directory named after it, in the current directory. Use unzip $1 -d "${target}" if you want to extract the archive to a directory alongside it instead.

  • Awesome, what's the meaning of ##*/ part of the last line of the function? Thanks! – Emanuil Rusev Dec 17 '18 at 11:21
  • Wouldn't it make more sense to do the trimming of everything up to the last / in the same line that removes the .zip. I'm new to bash so forgive me if the question is not very smart. – Emanuil Rusev Dec 17 '18 at 12:18
  • 1
    It would make more sense, unfortunately there’s no direct way to do so using the shell’s operators. – Stephen Kitt Dec 17 '18 at 12:22
  • Last question, what's that ##* syntax called? I'd like to search for it and learn more. – Emanuil Rusev Dec 17 '18 at 12:33
  • 1
    It’s part of parameter expansion; see this section of the Bash manual. – Stephen Kitt Dec 17 '18 at 12:45
6

Use unzip -d exdir zipfile.zip to extract a zipfile into a particular directory. In principle from reading your post literally you could write a function like this:

unzip_d () {
    unzip -d "$1" "$1"
}

Since you want the .zip extension removed though, you can use special variable syntax to do that:

unzip_d () {
    zipfile="$1"
    zipdir=${1%.zip}
    unzip -d "$zipdir" "$zipfile"
}
  • 1
    additional tip: use basename to make it more robust. (already upvoted though) **;-) – Fabby Dec 18 '18 at 10:49

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