1

I have a large directory with files like this:

file1.txt file1.meta file1.csv file2.txt file2.meta file2.csv file2.abc 

and I would like to create zip files like:

file1.zip file2.zip 

I have tried

ls -1 ~/TEMP | sed 's/\.[a-z]*//g' | uniq | awk '{print $NF}' | xargs -i zip {}.zip ~/TEMP/{}.* 

But that just gives an error message that the file cannot be fund. The problem is with the wildcard * I guess.

zip error: Nothing to do! (file1.zip) zip warning: name not matched: /home/user/TEMP/file.* 
7
  • @Theophrastus The folder has ~ 200000 files with different basenames, 'file' was just an example. I tried to get the unique basenames with sed 's/\.[a-z]*//g' | uniq. Commented Jan 15, 2018 at 5:10
  • have you tried this. zip file1.zip file1.* & zip file2.zip file2.* Commented Jan 15, 2018 at 5:11
  • 4
    for Q in *;do H=${Q%%.*};zip "${H}.zip" "$Q";done Commented Jan 15, 2018 at 5:27
  • In what directory are the files to be zipped located? I see an ls of the current working directory and an argument to zip of the ~/TEMP directory. Commented Jan 15, 2018 at 5:33
  • @Theophrastus Brilliant. H=${Q%%.*} is neat. Commented Jan 15, 2018 at 5:33

2 Answers 2

2

Spinning off from Jeff's idea, but not using a list:

for fname in *.*; do prefix=${fname%.*} [ ! -f "$fname" ] || [ -f "$prefix.zip" ] && continue zip "$prefix" "$prefix".* done 

This loop over all names in the current directory that contains at least one dot character.

The body of the loop extracts the filename prefix by removing the bit after the last dot in the current filename (use %% in place of % to remove from the first dot). It then tests whether the name was actually the name of a regular file (or a symbolic link to one) and whether the corresponding Zip archive for that file already exists or not.

If the file is a regular file (or symlink to one), and if the archive file does not exist, zip is invoked to create the archive.

1

One way, in bash (since you tagged it):

  1. Gather the list of filename prefixes into an associative array:

    declare -A prefixes for f in *; do prefixes[${f%%.*}]=1; done 
  2. Loop through the prefixes and create the zip files:

    for p in "${!prefixes[@]}"; do zip "$p" "$p".*; done 

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.