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
How to write shell script to create zip file for the files that had same string in file name
提问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 zip
will 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 nullglob
is 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 .txt
and .csv
that 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 gorilla
and I chmod +x gorilla
and 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 .txt
and .csv
and zip
them in the archive corresponding to the date: appending this to gorilla
will 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