How to compress all files from several subfolders?
Raw input:
➜ test tree
.
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
├── f6.doc
├── s1
│ ├── code
│ └── data
│ ├── f1.md
│ ├── f2.md
│ ├── f3.md
│ ├── f4.txt
│ ├── f5.csv
│ └── f6.doc
├── s2
│ ├── code
│ └── data
│ ├── f1.md
│ ├── f2.md
│ ├── f3.md
│ ├── f4.txt
│ ├── f5.csv
│ └── f6.doc
├── s3
│ ├── code
│ └── data
│ ├── f1.md
│ ├── f2.md
│ ├── f3.md
│ ├── f4.txt
│ ├── f5.csv
│ └── f6.doc
└── s4
├── code
└── data
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
└── f6.doc
12 directories, 30 files
Expected output
➜ test tree
.
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
├── f6.doc
├── s1
│ ├── code
│ └── data
│ ├── Archive.zip
│ ├── f1.md
│ ├── f2.md
│ ├── f3.md
│ ├── f4.txt
│ ├── f5.csv
│ └── f6.doc
├── s2
│ ├── code
│ └── data
│ ├── Archive.zip
│ ├── f1.md
│ ├── f2.md
│ ├── f3.md
│ ├── f4.txt
│ ├── f5.csv
│ └── f6.doc
├── s3
│ ├── code
│ └── data
│ ├── f1.md
│ ├── f2.md
│ ├── f3.md
│ ├── f4.txt
│ ├── f5.csv
│ └── f6.doc
└── s4
├── code
└── data
├── Archive.zip
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
└── f6.doc
12 directories, 33 files
I want files from subfolders(s1/s2/s4) to compress.
I tried to use command-line zip -r Archive.zip ./*
in each subfolder( s1/s2/s4) . It’s inconvenient because I have to enter same commands for three times.
How do I using a command once or writing a script to achieve this? I’m on OSX(10.12.6).
Something like this script can do the work:
for i in `find /path -type d -name data`;
do
if [ "$i" = "s3/data" ]
then continue
else cd "$i" && zip Archive.zip *
fi
done
P.S. Replace /path
with starting point of your directory tree
find . -type d -name data -execdir zip -jr data/Archive.zip data ';'
This find
command will find each data
directory under the current directory and execute
zip -jr data/Archive.zip data
in each of the sN
directories (the parent directory of the data
directories). This will also archive hidden files.
The -j
flag to zip
will strip the pathnames of the files added to the archive and the archive will be placed inside the data
directory.
This works because -execdir
basically does a cd
to the parent directory of the found thing before executing the command.
To avoid the s3
directory, use
find . -type d -name data ! -path "./s3/*" -execdir zip -jr data/Archive.zip data ';'
POSIXly (except for the zip
command obviously):
find . -path ./s3 -prune -o -type d -name data -exec sh -c '
for dir do
(cd "$dir" && zip -r Archive.zip .)
done' sh {} +
Or with zsh -o extendedglob
:
for dir (./**/data~*/s3/*(/N)) (cd $dir && zip -r Archive.zip .)
Or if you don’t want to search recursively for data
folders:
for dir (./^s3/data(/N)) (cd $dir && zip -r Archive.zip .)
Or to be even more specific (no need for extendedglob
here):
for dir (s[124]/data(/N)) (cd $dir && zip -r Archive.zip .)