1

I want to create bash script that find *.mp4 and zip it.

I use this:

#!/bin/sh
zip -r $(find . -name '*.mp4').zip $(find "/home/ehsan/Desktop" -name '*.pdf')

but not work and get this error:

zip error: Zip file structure invalid (./Bank_Mellat_v3.2_hassas-computer.com/Help.pdf)
2
  • In your question you say you want to zip .mp4 files but in your sample zip command you are using .pdf. Which is it? Also, are you trying to: a) .zip each individual file separately (a .zip per file) or b) add every file to a single .zip?
    – Drew
    Aug 2, 2015 at 12:45
  • edit question !. and i want to create each file to own zip. example: a.mp4 -> a.zip Aug 2, 2015 at 13:36

3 Answers 3

4

Zipping all files in one archive

You can zip all files with a basename matching *.mp4 found under the current directory into a single archive with the following command:

zip my_mp4_archive.zip $(find . -name "*.mp4")

Zipping each file in an archive of its own

The following script will zip each file individually, in the same directory as the file itself is stored.

files=$(find . -name "*.mp4")

for f in $files; do
  echo "Compressing $f"
  (cd $(dirname $f) && zip $(basename $f.zip) $(basename $f))
done
6
  • tanx for helping. but i want to create each mp4 to zip. example: a.mp4 to a.zip and b.mp4 to b.zip Aug 2, 2015 at 13:37
  • Alright, please take a look at my updated answer.
    – vindvaki
    Aug 2, 2015 at 13:51
  • For the record, I don't think zipping mp4 files will decrease their file size much at all, because they are already highly compressed.
    – vindvaki
    Aug 2, 2015 at 13:53
  • Doesn't works with spaces in the filename. I would give you a -1, but this makes no sense, as you are a rep 1 user.
    – A.B.
    Aug 2, 2015 at 17:30
  • Well then, I'm sure you can figure that out in your own. Good luck!
    – vindvaki
    Aug 2, 2015 at 17:42
3

zip alone can do this. Also note that zip-ing the mp4 files is inefficient as it won't give you any advantage as far as space is concerned as it is already in the compressed MPEG4 format.

To find all the .mp4 files recursively starting from current directory and save them as files.zip :

zip files.zip -r . -i '*.mp4'
  • -r denotes recursive operation

  • -i '*.mp4 specifies the only pattern we are interested in

EDIT :

After reading your comments it seems you want to find each .mp4 file and create the zip of that file only and also want to do this for all .mp4 files recursively. If that so :

find . -type f -name '*.mp4' -exec bash -c 'zip "${1%.mp4}".zip "$1"' _ {} \;

This will find all .mp4 files recursively staring from current directory and zip them each separately. So foo.mp4 will be zip-ped as foo.zip. Again you won't get any compression advantage.

2
  • +1 Good answer, but I have a question. It's bad to use find . -type f -name '*.mp4' -exec bash -c 'zip "${1%.mp4}".zip "$0"' {} \; instead?
    – A.B.
    Aug 2, 2015 at 17:35
  • 1
    @A.B. You need ${0%.mp4}, i know its a typo :) ..in this case it wont make any difference with $0 but imagine a regular case that you want to get all the arguments with $@, as $0 is not shown and bash -c starts arguments with 0 so yeah huge issue..
    – heemayl
    Aug 2, 2015 at 17:45
-1

Use this to compress all .mp4 files in the base directory and it's sub directories.

$ zip test.zip `find . -name \*.mp4 -print | tr "\n" " "`

Explanation:

To compress file zip file-name.zip path1 path2...

To get all file paths having .mp4 extension in base directory and all it's subdirectory use find:

find . -name \*.mp4 -print

To list all the output in one line separated by space like we require in our zip command pipe through tr "\n" " "

Putting everything together:

$ zip test.zip `find . -name \*.mp4 -print | tr "\n" " "`

Update After reading OP's comment:

Simply iterate through all the found .mp4 file's pathnames eg:

for p in `find . -name \*.mp4 -print`                                                                                                           
do
    zip $p.zip $p
done

If your filename contains a space character, you case us tr to replace space with backslash space

Eg: Use $p | tr ' ' "\' '" instead of $p.

3
  • tanx for helping. but i want to create each mp4 to zip. example: a.mp4 to a.zip and b.mp4 to b.zip Aug 2, 2015 at 13:38
  • -1 Doesn't works with spaces in the filename. And don't use `…`, use $(…) instead
    – A.B.
    Aug 2, 2015 at 17:29
  • @Ehsan updated answer.
    – yask
    Aug 3, 2015 at 10:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .