我有一堆以下格式的文件:
2014-11-19.8.ext
2014-11-26.1.ext
2014-11-26.2.blah.ext
2014-11-26_3.ext
2014-11-26.4.stuff_here.ext
2014-12-03.1. could be anything.ext
2014-12-032b.ext
2014-11-26 613 adva.ext
我的目标是迭代整个文件列表,并从中获取日期格式YYYY-MM-DD
并将其存储在变量中,YYYYMMDD
以进行进一步处理(在我的例子中,它将被推入touch
命令中)。
所以通常我会匹配这个正则表达式:(\d{4})-(\d{2})-(\d{2}).*
然后用来$1$2$3
获取我想要的模式,但是我不确定如何在bash
/中执行此操作zsh
。
如何在 shell 脚本中完成此操作?
答案1
使用参数扩展
$ touch 2014-11-19.8.ext 2014-11-26.1.ext
$ for f in *.ext; do d="${f:0:4}${f:5:2}${f:8:2}"; echo "$d"; done
20141119
20141126
${f:0:4}
表示从索引开始的4个字符0
,f
是变量名- 替换
echo "$d"
为您的代码
答案2
要循环当前目录中的每个文件并将其文件名与所需模式进行比较,然后设置一个包含日期片段的变量
for f in *
do
[[ $f =~ ^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])(.*) ]] &&
yourvar="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
done
这使用bash[[
使用正则表达式匹配的能力将日期片段放入 BASH_REMATCH 数组中。
答案3
您可以使用以下命令以交互方式完成此操作GNU sed
:
$ sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}.*\)/\1\2\3/g' stuff.txt
对于多个文件(如果在同一目录中并且目录中没有其他考虑的文件):
for file in *
do
if [ -f "$file" ]
then
sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\).*/\1\2\3/g' "$file"
fi
done
答案4
如果您使用 GNU Coreutils,您会看到:
$ date --date=2014-11-13 +"%Y%m%d"
20141113
然而:
$ date --date=2014-11-130ABCJUNK +"%Y%m%d"
date: invalid date ‘2014-11-130ABCJUNK’
因此,任务要简单得多:提取每个YYYY-MM-DDetc
文件名的前十个字符以获取日期本身,然后传递给date
重新格式化。
但是,如果我们使用 GNU Coreutils,我们可以跳过该date
命令,因为touch
有完全相同的--date=STRING
选项。
for file in * ; do
date=${file%${file##??????????}} # chop all but first ten
touch --date=$date -- "$file"
done
touch
但是,当我们依赖 GNU Coreutils时,为什么要以 POSIX 可移植方式进行这十个字符的切割呢?
for file in * ; do
date=${file:0:10}
touch --date=$date -- "$file"
done