1

I have a folder designed in the following way:

-parentDirectory
---folder1.zip
----item1
-----item1.zip
-----item2.zip
-----item3.zip
---folder2.zip
----item1
-----item1.zip
-----item2.zip
-----item3.zip
---folder3.zip
----item1
-----item1.zip
-----item2.zip
-----item3.zip

I would like to write a bash script that will loop through and unzip the folders and then go into each subdirectory of those folders and unzip the files and name those files a certain way.

I have tried the following

cd parentDirectory
find ./ -name \*.zip -exec unzip {} \;

count=1

for fname in *
do
    unzip
    mv $fname $attempt{count}.cpp
    count=$(($count + 1))
done

I thought the first two lines would go into the parentDirectory folder and unzip all zips in that folder and then the for loop would handle the unzipping and renaming. But instead, it unzipped everything it could and placed it in the parentDirectory. I would like to maintain the same directory structure I have.

Any help would be appreciated

hackr
  • 79
  • 7

1 Answers1

1

excerpt from man unzip

[-d exdir] An optional directory to which to extract files. By default, all files and subdirectories are recreated in the current directory; the -d option allows extraction in an arbitrary directory (always assuming one has permission to write to the directory).

It's doing exactly what you told it, and what would happen if you had done the same on the command line. Just tell it where to extract, since you want it to extract there.

see Ubuntu bash script: how to split path by last slash? for an example of splitting the path out of fname.

putting it all together, your command executed in the parentDirectory is

find ./ -name \*.zip -exec unzip {} \;

But you want unzip to extract to the directory where it found the file. I was going to just use backticks on dirname {} but I can't get it to work right, as it either executes on the "{}" literal before find, or never executes.

The easiest workaround was to write my own script for unzip which does it in place.

> cat unzip_in_place
unzip $1 -d `dirname $1`

> find . -name "*.zip" -exec ./unzip_in_place {} \;

You could probably alias unzip to do that automatically, but that is unwise in case you ever use other tools that expect unzip to work as documented.

Kenny Ostrom
  • 5,639
  • 2
  • 21
  • 30
  • Ah okay I see what you are saying. Maybe I am understanding incorrectly but I believe that all zip files will be in whatever I call my exdir. I want to be able to maintain the file structure I already have. – new_programmer_22 Jul 31 '19 at 17:19
  • I'm just saying use -d \`dirname {}\` to extract them relative to where they are. They are supposed to extract in the parent (current) directory if you don't tell them where to extract. I added the syntax, tested with -exec echo. – Kenny Ostrom Jul 31 '19 at 18:38
  • I do not understand why you have a second unzip with no arguments. I don't think that is doing what you think it is doing. Everything is unziped by the find because you told it to -exec unzip {} – Kenny Ostrom Jul 31 '19 at 18:41
  • I was confused about how the find command works. Also, it turns out I do not have to rename the files. So I simply just need to unzip everything and maintain the hierarchy of the directories. the second command listed above did not accomplish this. All unzipped files are in the parentDirectory – new_programmer_22 Jul 31 '19 at 18:46
  • My basic testing with exec echo was a bit hasty. I have reproduced and fixed that problem, and unzipped an actual zip file in the correct location. – Kenny Ostrom Jul 31 '19 at 19:14
  • You can go without creating a file `find ... -exec sh -c 'unzip "$1" -d "$(dirname "$1")"' -- {} \;` – KamilCuk Jul 31 '19 at 19:49