Bash: Zipping / regroupement de files par sous-string commune

J'ai environ 100 files.

Ils sont nommés comme ça.

3000_ABCD_XXXXXXX.csv 3000_ABCD_YYYYYYY.csv 3000_ABCD_XYXYZYZ.csv 3000_EFGH_XXXXXXX.csv 3000_EFGH_YYYYYYY.csv 3000_EFGH_XYXYZYZ.csv 3000_IJKL_XXXXXXX.csv 3000_IJKL_YYYYYYY.csv 3000_IJKL_XYXYZYZ.csv 

Actuellement, je zippe chaque file individuellement, mais je veux les regrouper en fonction de leur sous-string commune comme par exemple ABCD.zip va stocker

 3000_ABCD_XXXXXXX.csv 3000_ABCD_YYYYYYY.csv 3000_ABCD_XYXYZYZ.csv 

EFGH.zip va stocker

 3000_EFGH_XXXXXXX.csv 3000_EFGH_YYYYYYY.csv 3000_EFGH_XYXYZYZ.csv 

etc.

Je suis très nouveau pour les scripts Unix / Bash. Quelqu'un pourrait-il me diriger dans la bonne direction?

Edit: ABCD , EFGH , IJKL ne sont pas connus à l'avance. Leur position et leur largeur à l'intérieur du nom de file sont cependant garanties.

Avec zsh :

 setopt extendedglob typeset -A a for f (./*) { [[ $f = (#b)*_(*)_* ]] && a[$match]+=$f$'\0' } for z (${(k)a}) { echo zip ./$z.zip ${(ps:\0:)a[$z]} } 

(enlever l' echo pour le faire quand il est satisfait).

Utilisation de perl (à partir de zsh / bash ou de tout autre shell de type non-csh):

 perl -e 'for (@ARGV) {push @{$a{$1}}, $_ if (/_(.*)_/s)} system "echo", "zip", "./$_.zip", @{$a{$_}} for (keys %a)' ./*_*_* 

(encore une fois, enlever le "echo", pour le faire réellement).

Vous pourriez faire quelque chose comme:

 IFS=' ' set -f for group in $(set +f; printf '%s\n' 3000_*.csv | sed 's/3000_\([^_]*\).*/\1/' | LC_ALL=C uniq) do set +f zip "$group.zip" "3000_$group"*.csv done 

Devrait fonctionner dans bash ou un shell POSIX, à condition que les noms de files ne contiennent pas de returns.

Vous pouvez essayer le script ci-dessous.

 ##The find command below finds all the csv files in the current directory. find ~/home/file-directory-location/*.csv -type f > filenames.txt ##We know the second subssortingng after _ will contain the index. ##I am sorting the file based on that second subssortingng and getting the ##indices into a new file for zipping. ##The uniq will specify how many zip files we are creating. LC_ALL=C sort -t_ -k2,2 filenames.txt | cut -d '_' -f 2 | LC_ALL=C uniq > indexes ##Now, for the created indices just zip the CSV files based on the index name. while read index; do tar cvzf "$index".tgz /home/file-directory-location/3000_"$index"* done <indexes