2

I'm trying to devise an "elegant" solution to doing the following:

unzip applications/<abc>.zip -d applications/<abc>/
unzip applications/<def>.zip -d applications/<def>/
unzip applications/<ghi>.zip -d applications/<ghi>/
unzip applications/<jkl>.zip -d applications/<jkl>/

Brace expansions aren't applicable, they do the "reverse" of what I'm looking for (or am I missing something?).

Is a for-loop the way to go?
I had thought of using xargs or even exploiting history control (to backreference the argument with !:1 or something); but things quickly get more complicated instead of simpler.

I think I'm biased by regex-backreferencing; does something like that exist in the shell?

  • Is there a pattern to the abc/de/ghi that could be generated? – Jeff Schaller Dec 7 '18 at 17:55
  • 1
    If you're looking for sth more complicated than for f in *.zip; do unzip -d "${f%.zip}" "$f"; done then please add more info to your question. It's not at all obvious. – mosvy Dec 7 '18 at 18:02
4

A for loop, with some variable expansion rules may do what you want

for file in applications/*.zip
do
  unzip "$file" -d "${file%.zip}"
done

The expression ${file%.zip} means "the contents of $file with with .zip removed from the end".

So first time round the loop $file may read applications/abc.zip and so ${file%.zip} will read applications/abc.

  • You may need to append a / to unzip into the desired directory. – RudiC Dec 7 '18 at 22:03
  • @RudiC That may depend on the version of unzip; on CentOS 7 it'll create the directory as necessary. – Stephen Harris Dec 7 '18 at 22:36
2

You mentioned xargs. The xargs command appeared back in PWB/Unix, when neither the Thompson nor Mashey shell supported for loops. I think a for loop works best in your case. But it's kind of elegant to have programs make use of pipelines when possible, so here's how to do it with xargs:

printf "%s\n" abc def ghi jkl | xargs -I {} unzip applications/{}.zip -d applications/{}/
1

One possibility is a variable; you just have to assign it in a previous/separate command:

a=abc
unzip applications/"$a".zip -d applications/"$a"/
a=def
!unzip
1

Yes, a for loop is a good solution to your task.

for i in abc def ghi jkl; do
    unzip applications/"$i".zip -d applications/"$i"/
done

Or the same command on a single line,for use from the command line instead of a script:

for i in abc def ghi jkl; do unzip applications/"$i".zip -d applications/"$i"/; done

The quotes around$i are not necessary for the values from your example, but it's better to use quotes if you aren't sure that you will never have values with spaces or other special characters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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