0

I have a directory full of files *.CLM_01. I want to create 1 zip file with all files which have the value "005010X222" inside the file. Basically, there are a few files that have "005010X223" which I want to exclude from the zip. They are mutually exclusive. These values are in the data of the file not the file name.

I tried this but it' still zipping all files into 1 zip file

for f in *.CLM_01; do zip -ur test.zip $f | grep "005010X222" $f ; done
2
  • Each file should be archived into separate .zip file or all files should go into one .zip file? Commented Aug 26, 2022 at 19:01
  • all files should go into one .zip file Commented Aug 26, 2022 at 19:08

2 Answers 2

1

With zsh and GNU grep or compatible:

zip file.zip ${(0)"$(grep -l --null 005010X222 ./*.CLM_01)"}

If your grep doesn't take a --null but you can guarantee none of the file names contain newline characters:

zip file.zip ${(f)"$(grep -l 005010X222 ./*.CLM_01)"}

With other POSIX-like shells, you could do the same with the split+glob operator:

IFS='
' # split on newline
set -o noglob # disable glob
zip file.zip $(grep -l 005010X222 ./*.CLM_01)

If you have bsdtar, you can also pass the list of files null-delimited on its stdin with --null -T -:

grep -l --null 005010X222 ./*.CLM_01 | bsdtar --null -T - -acf file.zip

The GNU implementation of grep can also look for the *.CLM_01 files recursively by itself with:

grep --include='*.CLM_01' -rl --null 005010X222 . |
  bsdtar --null -T - -acf file.zip

That one isn't affected by the limit on the number of arguments that is passed to a command since the file paths are not passed as arguments to grep or bsdtar, but note that contrary to the glob-based solutions above, it will also consider hidden files.

With GNU grep, see also grep -L 005010X223 to list the files that do not contain 005010X223 instead of grep -l 005010X222 to list the ones that do contain 005010X222.

2
  • Is one limited by ARG_MAX / ulimit here? Commented Aug 26, 2022 at 19:48
  • @FelixJN, yes, except for the last one using grep -r | bsdtar Commented Aug 26, 2022 at 19:49
0

Use find with a quiet grep test:

find -name '*CLM_01' -exec grep -q '005010X222' {} \; -print0 | xargs -0 zip -u all_files.zip +

-q in grep is the quiet option, that only succeeds (exit code 0) on a match.

Best is to also use -u in zip in case xargs needs to call zip multiple times.

3
  • I tried this but received the error below find: missing argument to `-exec' zip warning: all_files.zip not found or empty zip warning: name not matched: + Commented Aug 26, 2022 at 20:02
  • @Hedi my bad - code corrected Commented Aug 27, 2022 at 8:40
  • Thank you! That worked Commented Aug 29, 2022 at 18:07

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.