I used >>
logsave path/log.txt find . -name "*.zip" -exec sh -c 'unzip -l {} | head -n 7' \; to get the list of files inside zip files in a particular folder. Here is a problem if the filename contains one or more spaces it is just skipping the files. Dir structure is


..........File1.zip **without space in name

...........Fi le2.zip **With space in name

...........F i l e 3.zip **with spaces in name

For above case file names in file1.zip is listed only. Can anyone recommend a solution.


Try enclosing your zip filenames in quotes so that unzip knows it is only one file name:

find . -name "*.zip" -exec sh -c 'unzip -l "{}" | head -n 7' \; 

The reason that we need to quote the {} in the above command is that we are passing a string to sh to run as a command line.

I will try to explain what is happening step by step:

For each file that matches *.zip, we will run the command sh -c 'unzip -l "{}" | head -n 7. sh -c 'blahblablah' takes the argument after -c and runs it as if it was entered on the command line.

So given a filename File A.zip (with a space) we will execute the command line:

unzip -l File A.zip | head -n 7

Now, what happens when we don't quote the filename is that before calling unzip, the shell will split the argument list into separate arguments, resulting in a list:

"unzip" "-l" "File" "A.zip"

which means that unzip will try to open the zip file File and look for the item A.zip inside the archive.

If we enclose the argument in quotes the shell will expand to the following argument list:

"unzip" "-l" "File A.zip"

Win! unzip will now try to open the zip file "File A.zip" and list its contents.

  • thanks.. A simple but effective change. can you please explain how quote is used to ignore spaces.
    – shekhar
    Nov 7 '12 at 15:47
  • I've updated my answer to try and explain why the quotes are needed. Nov 7 '12 at 16:00

You can use it with for too.

for file in *.zip; do unzip -l "$file" | head -n 7; done

  • 1
    interesting! I first thought this wouldn't work because it would be the same as "for file in $(ls *zip) .... but then I tried and it actually works, even though i dont exactly understand why/how... some detail of shell wildcard handling that i do not yet understand ;) thanks!
    – Henning
    Feb 20 '20 at 2:11
  • Don't need to use $(ls *.zip) - in fact, it can be a little bit messy if the filenames contains spaces (try it). The correct way to tell shell script that you need to get a file list is using the wildcard *. You can try it with subdirs too, like "for file in /dir/subdir/*.zip; do echo $file; done" :) Feb 21 '20 at 4:28
  • 1
    I tried it and it worked and that was why I said thanks ;)
    – Henning
    Feb 25 '20 at 19:07

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.