Can a shell shell unzip all files in a directory?

I saw cycles for unpacking all zip files in a directory. However, before I run this, I would rather make sure that what I am about to start will work correctly:

for i in dir; do cd $i; unzip '*.zip'; rm -rf *.zip; cd ..; done 

Basically, I want him to look at the output of "dir" to see all the folders for each cd directory in it, unzip all the zip archives, then delete them, then cd go back and do it again until they are gone.

Is this something I should do in one command, or should I do it in Perl?

+6
directory loops shell unzip
source share
5 answers

partially tested:

 find . -type d -exec sh -c "cd \"{}\" ; unzip \"*.zip\" ; rm \"*.zip\" " \; 

executes a cd / unzip / rm chain for each subdir.

+1
source share

In general, you should be fine. To debug only the prefix, all the commands in the echo loop will tell you how the variables expand. You can also always use rm -i to query instead of rm continuing with -f .

Single quotes in your unzip call will only unzip files named *.zip , i.e. * will not expand. Instead, use double quotes (or no quotes at all).

Now your loop assumes that all $i directories are under the current. A more general solution would be to use a directory stack ( pushd and popd );

 for i in $dir; do pushd $i unzip *.zip rm -rf *.zip popd done 
+2
source share

A few points added to what others said:

  • If you put the parameter in single quotes, for example, in '*.zip' , the shell will not perform the wild card extension, and unpack it will try to process the archive, which is literally called *.zip
  • Do not use -r as a parameter for rm if you just want to delete individual files. This is just unnecessarily dangerous, since any recursive deletion of subdirectories is probably not intended.
  • You should check the unzip return code and only delete the zip file if the decompression is successful (for example, you could say if unzip *.zip; then rm *.zip; fi or even use the explicit for loop to process ZIP files one at a time)
+2
source share

Use * to get the contents of the current directory:

 for i in *; do cd "$i"; ...etc... ; done 

You must also make sure that something is a directory before trying to connect to it. In bash, this is done as follows:

 if [ -d "$i" ]; then ...etc... ; fi 

You must also be careful to ensure that the decompression operation succeeded before deleting the zip file. There is no need to use recursive force to delete a single file.

I think this pushes the limit for the fact that it makes sense to draw one line. Put it in a shell script and format it on several lines.

+1
source share

When you want to know if something will work, but beware of its devastating consequences, do it a little at a time:

Make sure you get the files you need:

 for i in dir; do cd $i; echo $i; cd ..; done 

Make sure you can unzip files before deleting files:

 for i in dir; do cd $i; unzip '*.zip'; cd ..; done 

And before you do a full recording, make a backup copy of your directory.

0
source share

All Articles