tinlinnsoe
tinlinnsoe

Reputation: 173

How to write shell script to create zip file for the files that had same string in file name

How to write simple shell script to create zip file.
I want to create zip file by collecting files with same string pattern in their file names from a folder.

For example, there may be many files under a folder.

After running the shell script, the result must be following three zip files.

Please give me right direction to create simple shell script to output the result as above.

Upvotes: 0

Views: 13498

Answers (3)

gniourf_gniourf
gniourf_gniourf

Reputation: 46823

Since zip will update the archive, this will do:

shopt -s nullglob
for file in *.{txt,csv}; do [[ $file =~ _([[:digit:]]{8})_ ]] && zip "${BASH_REMATCH[1]}.zip" "$file"; done

The shopt -s nullglob is because you don't want to have unexpanded globs if there are no matching files.


Everything below this line is my old answer...

First, get all the possible dates. Heuristically, this could be the files ending in .txt and .csv that match the regex _[[:digit:]]{8}_:

#!/bin/bash
shopt -s nullglob
declare -A dates=()
for file in *.{csv,txt}; do
    [[ $file =~ _([[:digit:]]{8})_ ]] && dates[${BASH_REMATCH[1]}]=
done
printf "Date found: %s\n" "${!dates[@]}"

This will output to stdout all the dates found in the files. E.g. (I called the previous snipped gorilla and I chmod +x gorilla and touched a few files for demo):

$ ls
banana_20010101_gorilla.csv  gorilla_20140502_bonobo.csv
gorilla                      notthisone_123_lol.txt
gorilla_20140502_banana.txt
$ ./gorilla
Date found: 20140502
Date found: 20010101

Next step, for each date found, get all the files ending in .txt and .csv and zip them in the archive corresponding to the date: appending this to gorilla will do the job:

for date in "${!dates[@]}"; do
    zip "$date.zip" *"_${date}_"*.{csv,txt}
done

Full script after removing the flooding part:

#!/bin/bash
shopt -s nullglob
declare -A dates=()
for file in *.{csv,txt}; do
    [[ $file =~ _([[:digit:]]{8})_ ]] && dates[${BASH_REMATCH[1]}]=
done
for date in "${!dates[@]}"; do
    zip "$date.zip" *"_${date}_"*.{csv,txt}
done

Edit. I overlooked your requirement with one line command. Then here's the one-liner:

shopt -s nullglob; declare -A dates=(); for file in *.{csv,txt}; do [[ $file =~ _([[:digit:]]{8})_ ]] && dates[${BASH_REMATCH[1]}]=; done; for date in "${!dates[@]}"; do zip "$date.zip" *"_${date}_"*.{csv,txt}; done

:)

Upvotes: 1

Adrian Frühwirth
Adrian Frühwirth

Reputation: 45566

#!/bin/bash

for file in *_????????_*.csv *_????????_*.txt; do
        [ -f "${file}" ] || continue
        date=${file#*_}  # adjust this and next line depending
        date=${date%_*}  # on your actual prefix/suffix
        echo "${date}"
done | sort -u | while read date; do
        zip "${date}.zip" *${date}*
done

Upvotes: 1

choroba
choroba

Reputation: 241848

#! /bin/bash
dates=$(ls ?????_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_???.{csv,txt} \
    | cut -f2 -d_ | sort -u)

for date in $dates ; do
    zip $date.zip ?????_"$date"_???.{csv,txt}
done

Upvotes: 0

Related Questions