Celeb Glow
general | March 24, 2026

How can I recursively zip files in their own folder?

I have the following directory structure:

/Data - file 1 - file 2 /Folder1 - file 3 - file 4 /Folder2 - file 5 - file 6 /Folder3 - file 7 - file 8

In Linux I want to zip files (excluding folders) in every directory and create a 7z (or zip) archive in each folder resulting the following:

/Data Data.7z (Note: this should contain only file1 & 2, not any sub directories) /Folder1 Folder1.7z (this should contain only file3 & 4, not any sub directories) /Folder2 Folder2.7z (this should contain only file5 & 6, no Folder3) /Folder3 Folder3.7z (should contain only file7 & 8)

Following script works in the first directory but not in the sub-directories :

for i in */ ; do base=$(basename “$i”) ; cd $base ; 7za a -t7z -r $base * ; .. ; cd .. ; done;

How can I achieve this?

2

2 Answers

If you want to use 7z, the tricky part seems to be persuading it not to recurse; the documentation's indicated -r- switch appears to be non-functional, and the suggested workaround from the software's author is to exclude subdirectories with the wildcard expression -x!*/

So, given

$ tree Data
Data
├── file1
├── file2
├── Folder1
│   ├── file3
│   └── file4
├── Folder2
│   ├── file5
│   └── file6
└── Folder3 ├── file7 └── file8
3 directories, 8 files

then

find Data -type d -execdir sh -c 'cd "$1" && 7z a "$1".7z -x!*/ && cd -' sh {} \;

results in

$ tree Data
Data
├── Data.7z
├── file1
├── file2
├── Folder1
│   ├── file3
│   ├── file4
│   └── Folder1.7z
├── Folder2
│   ├── file5
│   ├── file6
│   └── Folder2.7z
└── Folder3 ├── file7 ├── file8 └── Folder3.7z
3 directories, 12 files

where for example we can check that Folder2.7z contains only its own folder's files using

$ 7z l Data/Folder2/Folder2.7z
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_CA.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU P9600 @ 2.53GHz (1067A),ASM)
Scanning the drive for archives:
1 file, 128 bytes (1 KiB)
Listing archive: Data/Folder2/Folder2.7z
--
Path = Data/Folder2/Folder2.7z
Type = 7z
Physical Size = 128
Headers Size = 128
Solid = -
Blocks = 0 Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2018-02-12 18:37:37 ....A 0 0 file5
2018-02-12 18:37:37 ....A 0 0 file6
------------------- ----- ------------ ------------ ------------------------
2018-02-12 18:37:37 0 0 2 files

Note: !*/ may require additional escaping in environments (such as the interactive bash shell) where ! is a history expansion operator.

1

This is untested code, only used with 'echo', since I don't like to end with multiple zip files. And it is phantasy zip syntax, since I don't know 7za, but I will explain:

find . -type d -execdir /.../ad-hoc.sh {} ";"

The script ad-hoc.sh has to be adressed with an absolute path and should not be in the current path, to not affect the outcome, but it might be in the parentdir:

find . -type d -execdir $PWD/../ad-hoc.sh {} ";"

and, if not made executable, be explicitly invoked:

find . -type d -execdir bash $PWD/../ad-hoc.sh {} ";"

Find shall look in the current dir, only for files of type d (dirs), where to -execute a bashscript with parameter {}, the directory found.

Ok - what is the ad-hoc.sh, we execute in the dir and subdirs? It's another find:

#!/bin/bash
dir=$1
find $dir -maxdepth 1 -type f -exec echo zip -o "$dir.zip" {} +

-maxdepth 1 prevents find to search subdirs, -type says to just operate on files. -exec launches a command, for testing "echo zip ...", but if it looks promising (you do backups often, don't you?), you - well, here starts my pseudo code: -o:= -output "$PWD.zip", and {} + is the file list.

tree
.
├── buch-klein.kry
├── buch.kry
├── crypt
│   ├── moveto.sh.crypt
│   └── sub1
│   ├── foo.crypt
│   └── sub2
│   └── bar.crypt
├── original
│   ├── 1
│   │   └── 2
│   │   └── 3
│   ├── moveto.sh
│   └── sub1
│   └── sub2
│   └── up3 -> ../../../nr
├── outputfile.txt
├── rot.sh
└── zoom.sh
find . -type d -execdir $PWD/../ad-hoc.sh {} ";"
zip -o ./..zip ././buch-klein.kry ././rot.sh ././buch.kry ././zoom.sh ././outputfile.txt
zip -o ./original.zip ./original/moveto.sh
zip -o ./crypt.zip ./crypt/moveto.sh.crypt
zip -o ./sub1.zip ./sub1/foo.crypt
zip -o ./sub2.zip ./sub2/bar.crypt

Every file with extension is a regular file, and every file without is a directory or a symlink to a dir (up3).

The {} has to be the last element of a find -exec command before the terminating ";" or +, so you have to build your 7z-command accordingly.

so if your 7za command is

 7za a -t7z -r $dir.7za *

the ad-hoc.sh might look like this:

#!/bin/bash
dir=$1
find $dir -maxdepth 1 -type f -exec echo 7za -t7z -r "$dir.7za" {} +
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy