bash 如何编写shell脚本为文件名中具有相同字符串的文件创建zip文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23428007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:22:25  来源:igfitidea点击:

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

linuxbashshell

提问by tinlinnsoe

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.

如何编写简单的 shell 脚本来创建 zip 文件。
我想通过从文件夹中收集文件名中具有相同字符串模式的文件来创建 zip 文件。

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

例如,一个文件夹下可能有很多文件。

  • xxxxx_20140502_xxx.txt
  • xxxxx_20140502_xxx.txt
  • xxxxx_20140503_xxx.txt
  • xxxxx_20140503_xxx.txt
  • xxxxx_20140504_xxx.txt
  • xxxxx_20140504_xxx.txt
  • xxxxx_20140502_xxx.txt
  • xxxxx_20140502_xxx.txt
  • xxxxx_20140503_xxx.txt
  • xxxxx_20140503_xxx.txt
  • xxxxx_20140504_xxx.txt
  • xxxxx_20140504_xxx.txt

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

运行shell脚本后,结果必须是三个zip文件。

  • 20140502.zip
  • 20140503.zip
  • 20140504.zip
  • 20140502.zip
  • 20140503.zip
  • 20140504.zip

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

请给我正确的方向来创建简单的 shell 脚本以输出如上的结果。

回答by Adrian Frühwirth

#!/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

回答by gniourf_gniourf

Since zipwill update the archive, this will do:

由于zip将更新存档,因此将执行以下操作:

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

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

shopt -s nullglob是因为如果没有匹配的文件,您不希望有未扩展的 glob。



Everything below this line is my old answer...

此行以下的所有内容都是我的旧答案...

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

首先,获取所有可能的日期。启发式,这可能是在结尾的文件.txt.csv相匹配的正则表达式_[[: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 gorillaand I chmod +x gorillaand touched a few files for demo):

这会将在文件中找到的所有日期输出到标准输出。例如(我调用了之前的 snippedgorilla并且我chmod +x gorilla触摸了一些演示文件):

$ 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 .txtand .csvand zipthem in the archive corresponding to the date: appending this to gorillawill do the job:

下一步,对于找到的每个日期,获取以.txt和结尾的所有文件,.csv并将zip它们放在与日期对应的存档中:将其附加到gorilla将完成这项工作:

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

:)

:)

回答by choroba

#! /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