[arch-general] Unzip archive in which are multiple sub zip archiers?
Hi, I just get a ZIP archive and want to unzip it. I'm using unzip to unpack this archive. But when I did first unzip command, I get more ZIP archives, which have again in it more ZIP archives. Is there a command or application whic can unzip this ZIP archive and it's sub ZIP archives at once? -- Regards from Pal
On 17 April 2015 at 18:08, Csányi Pál <csanyipal@gmail.com> wrote:
Hi,
I just get a ZIP archive and want to unzip it.
I'm using unzip to unpack this archive.
But when I did first unzip command, I get more ZIP archives, which have again in it more ZIP archives.
Is there a command or application whic can unzip this ZIP archive and it's sub ZIP archives at once?
Hey, That doesn't sound like a common enough use case that someone would have written a program just for that purpose. But you could write a simple shell script (or whatever you prefer) to recursively unzip a bunch of zip files. Keep in mind not to unzip the same files forever of course. Regards, Maarten
On April 17, 2015 12:29:36 PM EDT, Maarten de Vries <maarten@de-vri.es> wrote:
On 17 April 2015 at 18:08, Csányi Pál <csanyipal@gmail.com> wrote:
Hi,
I just get a ZIP archive and want to unzip it.
I'm using unzip to unpack this archive.
But when I did first unzip command, I get more ZIP archives, which have again in it more ZIP archives.
Is there a command or application whic can unzip this ZIP archive and it's sub ZIP archives at once?
Hey,
That doesn't sound like a common enough use case that someone would have written a program just for that purpose. But you could write a simple shell script (or whatever you prefer) to recursively unzip a bunch of zip files. Keep in mind not to unzip the same files forever of course.
Regards, Maarten
If you're not familiar with shell scripting I can write one (with detailed comments). I need the practice. It'll have to wait until later today, however. -- vixsomnis
2015-04-17 18:53 GMT+02:00 Christian Demsar <vixsomnis@fastmail.com>:
On April 17, 2015 12:29:36 PM EDT, Maarten de Vries <maarten@de-vri.es> wrote:
On 17 April 2015 at 18:08, Csányi Pál <csanyipal@gmail.com> wrote:
I just get a ZIP archive and want to unzip it.
I'm using unzip to unpack this archive.
But when I did first unzip command, I get more ZIP archives, which have again in it more ZIP archives.
Is there a command or application whic can unzip this ZIP archive and it's sub ZIP archives at once?
That doesn't sound like a common enough use case that someone would have written a program just for that purpose. But you could write a simple shell script (or whatever you prefer) to recursively unzip a bunch of zip files. Keep in mind not to unzip the same files forever of course.
If you're not familiar with shell scripting I can write one (with detailed comments). I need the practice.
OK, write one and I'm willing to try it out and modify if it would have GPL licence. :) I'm newbie in bash shell scripting. -- Regards from Pal
On Fri, Apr 17, 2015, at 01:12 PM, Csányi Pál wrote:
2015-04-17 18:53 GMT+02:00 Christian Demsar <vixsomnis@fastmail.com>:
On April 17, 2015 12:29:36 PM EDT, Maarten de Vries <maarten@de-vri.es> wrote:
On 17 April 2015 at 18:08, Csányi Pál <csanyipal@gmail.com> wrote:
I just get a ZIP archive and want to unzip it.
I'm using unzip to unpack this archive.
But when I did first unzip command, I get more ZIP archives, which have again in it more ZIP archives.
Is there a command or application whic can unzip this ZIP archive and it's sub ZIP archives at once?
That doesn't sound like a common enough use case that someone would have written a program just for that purpose. But you could write a simple shell script (or whatever you prefer) to recursively unzip a bunch of zip files. Keep in mind not to unzip the same files forever of course.
If you're not familiar with shell scripting I can write one (with detailed comments). I need the practice.
OK, write one and I'm willing to try it out and modify if it would have GPL licence. :) I'm newbie in bash shell scripting.
-- Regards from Pal
http://pastebin.com/YJFvUt13 It works on my (single) test case so far. I don't have any more time to work in this right now, but I'll test edge cases and add more comments later (feedback is welcome). If you use this, please, please, please back up your zip file in a different directory. I haven't tested it thoroughly enough to be confident that it won't suck your files into the black hole of /dev/null. On a side note, it does check to make sure the directory doesn't exist, so it shouldn't clobber anything. That goes for the internal zips as well. The only cryptic thing in the $IFS env var. That's needed for newline delimiters, so I can iterate over the zip files in a directory. I'll experiment with leaving that section out. There's probably a bash guru out there that can do this with a one-liner, but that's beyond my skills (I'm a newbie at bash, too). -- vixsomnis
On 04/17/2015 10:19 PM, Christian Demsar wrote:
It works on my (single) test case so far. I don't have any more time to work in this right now, but I'll test edge cases and add more comments later (feedback is welcome).
If you use this, please, please, please back up your zip file in a different directory. I haven't tested it thoroughly enough to be confident that it won't suck your files into the black hole of /dev/null.
On a side note, it does check to make sure the directory doesn't exist, so it shouldn't clobber anything. That goes for the internal zips as well.
The only cryptic thing in the $IFS env var. That's needed for newline delimiters, so I can iterate over the zip files in a directory. I'll experiment with leaving that section out.
There's probably a bash guru out there that can do this with a one-liner, but that's beyond my skills (I'm a newbie at bash, too).
You should be able to avoid fiddling with IFS by using: shopt -s nullglob zipfiles=(*.zip) It also has the advantage of not spawning a process to find zip files. The nullglob option is needed in case there are no zip files, otherwise (*.zip) will turn into a literal ('*.zip') instead of an empty array. Regards, Maarten
On 04/17/2015 10:34 PM, Maarten de Vries wrote:
On 04/17/2015 10:19 PM, Christian Demsar wrote:
It works on my (single) test case so far. I don't have any more time to work in this right now, but I'll test edge cases and add more comments later (feedback is welcome).
If you use this, please, please, please back up your zip file in a different directory. I haven't tested it thoroughly enough to be confident that it won't suck your files into the black hole of /dev/null.
On a side note, it does check to make sure the directory doesn't exist, so it shouldn't clobber anything. That goes for the internal zips as well.
The only cryptic thing in the $IFS env var. That's needed for newline delimiters, so I can iterate over the zip files in a directory. I'll experiment with leaving that section out.
There's probably a bash guru out there that can do this with a one-liner, but that's beyond my skills (I'm a newbie at bash, too).
You should be able to avoid fiddling with IFS by using:
shopt -s nullglob zipfiles=(*.zip)
It also has the advantage of not spawning a process to find zip files. The nullglob option is needed in case there are no zip files, otherwise (*.zip) will turn into a literal ('*.zip') instead of an empty array.
Regards, Maarten
Oh, and I forgot to mention that when you do that you ought to loop over the array as (bash is a bit weird): for file in "${zipfiles[@]}"; do Otherwise paths with spaces would be a problem. Regards, Maarten
On Fri, Apr 17, 2015, at 04:46 PM, Maarten de Vries wrote:
On 04/17/2015 10:34 PM, Maarten de Vries wrote:
On 04/17/2015 10:19 PM, Christian Demsar wrote:
It works on my (single) test case so far. I don't have any more time to work in this right now, but I'll test edge cases and add more comments later (feedback is welcome).
If you use this, please, please, please back up your zip file in a different directory. I haven't tested it thoroughly enough to be confident that it won't suck your files into the black hole of /dev/null.
On a side note, it does check to make sure the directory doesn't exist, so it shouldn't clobber anything. That goes for the internal zips as well.
The only cryptic thing in the $IFS env var. That's needed for newline delimiters, so I can iterate over the zip files in a directory. I'll experiment with leaving that section out.
There's probably a bash guru out there that can do this with a one-liner, but that's beyond my skills (I'm a newbie at bash, too).
You should be able to avoid fiddling with IFS by using:
shopt -s nullglob zipfiles=(*.zip)
It also has the advantage of not spawning a process to find zip files. The nullglob option is needed in case there are no zip files, otherwise (*.zip) will turn into a literal ('*.zip') instead of an empty array.
Regards, Maarten
Oh, and I forgot to mention that when you do that you ought to loop over the array as (bash is a bit weird):
for file in "${zipfiles[@]}"; do
Otherwise paths with spaces would be a problem.
Regards, Maarten
I'll try to use the globbing. That's new to me. Is there anything else you saw that was odd? This is the first non-trivial script I've written (recursion in bash!), so I'm not sure about the placement of the functions, etc. Is there a way to declare the functions like in C? I couldn't figure that out from the section on functions in Advanced Bash Scripting. -- vixsomnis
On 04/17/2015 10:57 PM, Christian Demsar wrote:
I'll try to use the globbing. That's new to me.
Is there anything else you saw that was odd? This is the first non-trivial script I've written (recursion in bash!), so I'm not sure about the placement of the functions, etc.
At a second look, this check might also be a problem: if [ $zipFiles ]; then To be honest I'm not sure what bash will do with that when $zipFiles is an array. The check isn't really needed with an array since looping over an empty array won't do anything anyway. When you do need it you can get the number of elements in an array in bash with ${#array[@]} and test on that. Knowing how bash arrays work can be very useful in writing effective bash scripts. If you haven't yet I would recommend reading up on their specifics. In bash (and some other shells), you might also prefer [[ ]] for tests over [ ]. It is somewhat less confusing in some situations, but be aware that it is not POSIX. Then again, arrays aren't POSIX either. Just be sure to use a proper bash shebang and not #!/bin/sh when you're using bash features (you already did this, but it's important so I'm emphasizing ;) ). I also saw that you check for read permissions before trying to extract the zip file. It doesn't hurt, but it's generally better to just try doing what you want to do and detect errors by checking the exit code of programs you run. Otherwise you will likely forget to check for some uncommon error conditions. In some cases it can even happen that the error conditions are not present when you test for them, but they are later when you try to extract the file (or do something else with it) because something or someone changed something in between.
Is there a way to declare the functions like in C? I couldn't figure that out from the section on functions in Advanced Bash Scripting. If you mean first declare a function and define it later: no, you can't do that in bash. On the other hand, you can use a function B the body of function A before B is defined, as long as you don't call A until B is defined. So in general it doesn't really matter. For example, this will work fine:
foo() { bar } bar() { echo "Hello world!" } foo I hope my comments are useful. If not, feel free to ignore them ;) Regards, Maarten
2015-04-17 23:38 GMT+02:00 Maarten de Vries <maarten@de-vri.es>:
On 04/17/2015 10:57 PM, Christian Demsar wrote:
I'll try to use the globbing. That's new to me.
Is there anything else you saw that was odd? This is the first non-trivial script I've written (recursion in bash!), so I'm not sure about the placement of the functions, etc.
At a second look, this check might also be a problem:
if [ $zipFiles ]; then
To be honest I'm not sure what bash will do with that when $zipFiles is an array. The check isn't really needed with an array since looping over an empty array won't do anything anyway. When you do need it you can get the number of elements in an array in bash with ${#array[@]} and test on that. Knowing how bash arrays work can be very useful in writing effective bash scripts. If you haven't yet I would recommend reading up on their specifics.
In bash (and some other shells), you might also prefer [[ ]] for tests over [ ]. It is somewhat less confusing in some situations, but be aware that it is not POSIX. Then again, arrays aren't POSIX either. Just be sure to use a proper bash shebang and not #!/bin/sh when you're using bash features (you already did this, but it's important so I'm emphasizing ;) ).
I also saw that you check for read permissions before trying to extract the zip file. It doesn't hurt, but it's generally better to just try doing what you want to do and detect errors by checking the exit code of programs you run. Otherwise you will likely forget to check for some uncommon error conditions. In some cases it can even happen that the error conditions are not present when you test for them, but they are later when you try to extract the file (or do something else with it) because something or someone changed something in between.
Is there a way to declare the functions like in C? I couldn't figure that out from the section on functions in Advanced Bash Scripting.
If you mean first declare a function and define it later: no, you can't do that in bash. On the other hand, you can use a function B the body of function A before B is defined, as long as you don't call A until B is defined. So in general it doesn't really matter. For example, this will work fine:
foo() { bar }
bar() { echo "Hello world!" }
foo
I hope my comments are useful. If not, feel free to ignore them ;)
Regards, Maarten
Thank you all for help. The script works, it can unzip archives recursively. -- Regards from Pal
On Mon, Apr 20, 2015, at 08:27 AM, Csányi Pál wrote:
2015-04-17 23:38 GMT+02:00 Maarten de Vries <maarten@de-vri.es>:
On 04/17/2015 10:57 PM, Christian Demsar wrote:
I'll try to use the globbing. That's new to me.
Is there anything else you saw that was odd? This is the first non-trivial script I've written (recursion in bash!), so I'm not sure about the placement of the functions, etc.
At a second look, this check might also be a problem:
if [ $zipFiles ]; then
To be honest I'm not sure what bash will do with that when $zipFiles is an array. The check isn't really needed with an array since looping over an empty array won't do anything anyway. When you do need it you can get the number of elements in an array in bash with ${#array[@]} and test on that. Knowing how bash arrays work can be very useful in writing effective bash scripts. If you haven't yet I would recommend reading up on their specifics.
In bash (and some other shells), you might also prefer [[ ]] for tests over [ ]. It is somewhat less confusing in some situations, but be aware that it is not POSIX. Then again, arrays aren't POSIX either. Just be sure to use a proper bash shebang and not #!/bin/sh when you're using bash features (you already did this, but it's important so I'm emphasizing ;) ).
I also saw that you check for read permissions before trying to extract the zip file. It doesn't hurt, but it's generally better to just try doing what you want to do and detect errors by checking the exit code of programs you run. Otherwise you will likely forget to check for some uncommon error conditions. In some cases it can even happen that the error conditions are not present when you test for them, but they are later when you try to extract the file (or do something else with it) because something or someone changed something in between.
Is there a way to declare the functions like in C? I couldn't figure that out from the section on functions in Advanced Bash Scripting.
If you mean first declare a function and define it later: no, you can't do that in bash. On the other hand, you can use a function B the body of function A before B is defined, as long as you don't call A until B is defined. So in general it doesn't really matter. For example, this will work fine:
foo() { bar }
bar() { echo "Hello world!" }
foo
I hope my comments are useful. If not, feel free to ignore them ;)
Regards, Maarten
Thank you all for help. The script works, it can unzip archives recursively.
-- Regards from Pal
Thanks for the tips Maarten. I was thinking of trying to implement a more advanced version of this script as an open source project, but there already is one. https://aur.archlinux.org/packages/dtrx/ I tested it on a 7z{ xz{ txt }, tar.gz{ zip{ txt } } } and it worked pretty much flawlessly, albeit leaving behind the extracted inner archives (which would be annoying to delete if you had a mess of different sorts of archives like the test file I used). In any case, I recommend that over my script if you ever need to do some intelligent archive extracting again. -- vixsomnis
participants (3)
-
Christian Demsar
-
Csányi Pál
-
Maarten de Vries