Bash:共通部分文字列でファイルを圧縮/グループ化する

Bash:共通部分文字列でファイルを圧縮/グループ化する

約100個のファイルがあります。

彼らの名前はこんな感じです。

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

現在、各ファイルを個別に圧縮していますが、共通の部分文字列に基づいてグループ化したいと思いますABCD.zip

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

EFGH.zip救う

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

など。

私はUnix / Bashスクリプトに初めて触れました。誰もが正しい方向に私を指すことができますか?

編集者:ABCDEFGHIJKL事前に知らなかった。ただし、ファイル名の場所と幅は保証されます。

答え1

そして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]}
}

(満足すれば削除してecho実際に実行します。)

perl(またはzshcshbashに似ていない他のシェルで)使用:

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

"echo",実際に実行するには削除してください。)

答え2

次のことができます。

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

bashファイル名に改行文字が含まれていない場合は、POSIXシェルで機能します。

答え3

以下のスクリプトを試してみてください。

##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 substring after _ will contain the index. 
##I am sorting the file based on that second substring 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

関連情報