aa_te, bb_co, cc_co, dd_xy
我想删除旧文件,并根据文件名中的前五个字符 ( ) 以及日期和时间仅保留每个文件模式中的最新文件。
笔记:
所有文件都有.err.mm_dd_yyyy hr_mm_ss am/pm.csv
排序。文件名长度可能会有所不同
示例:我的文件夹中有以下 CSV 文件c/test
aa_te_bbc_207_mc_ghghgh.err.05_31_2021 7_15_04 am.csv
aa_te_ccd.err.05_30_2021 7_55_35 pm.csv
bb_co_ddee_354_m.err.06_15_2021 5_20_00 am.csv
bb_co_eeffff.err.06_15_2021 5_20_01 am.csv
cc_co_eeffyy_cc.err.04_10-2020 12_00_00 am.csv
dd_xy_eeffyyvv_cc.err.04_10-2020 12_00_00 am.csv
dd_xy_eeffyyvv_cc.err.04_10-2020 12_10_25 am.csv
我对之后的期望仍然是:
aa_te_bbc_207_mc_ghghgh.err.05_31_2021 7_15_04 am.csv
bb_co_eeffff.err.06_15_2021 5_20_01 am.csv
cc_co_eeffyy_cc.err.04_10-2020 12_00_00 am.csv
dd_xy_eeffyyvv_cc.err.04_10-2020 12_10_25 am.csv
答案1
rm
如果可以的话,删除最后一行中的“echo”
#!/bin/bash
# search dir
dir=./
# function conv PATTERN
conv() {
# extract date from file name: 06_15_2021 5_20_00 am
date=${1%.*}
date=${date##*.}
# sanitize date string: 06/15/2021 5:20:00-am
date=${date//[^0-9AaPpMm]/-}
date=${date/-//}
date=${date/-//}
date=${date/-/ }
date=${date/-/:}
date=${date/-/:}
# print epoch time
date --date="$date" +%s || return 1
return 0
}
# search: *m.csv
for file in "$dir"*[Mm].[Cc][Ss][Vv]
do
[ -f "$file" ] || continue
# file name: bb_co_ddee_354_m.err.06_15_2021 5_20_00 am.csv
file=${file##*/}
# base name: bb_co_ddee_354_m
name=${file%%.*}
# suffix: ddee_354_m
del=${name#*_}
del=${del#*_}
# short name = base name - _suffix: bb_co
name=${name%_$del}
# convert date
date=$(conv "$file") || continue
# search short name: bb_co_*m.csv
for search in "${dir}${name}"_*[Mm].[Cc][Ss][Vv]
do
# delete older file
date2=$(conv "${search##*/}") || continue
[ "$date" -gt "$date2" ] && echo rm "$search"
done
done
答案2
使用zsh
代替bash
,你可以这样做:
#! /bin/zsh -
zmodload zsh/datetime
typeset -A latest=()
all=(
*.err.*.csv(Nnoe['LC_ALL=C strftime -rs REPLY %m_%d_%Y_%I_%M_%S_%p ${${${REPLY:r}##*.err.}//[- ]/_}'])
)
for file in $all; do
latest[$file[1,5]]=$file
done
keep=($latest)
echo rm -f -- ${all:|keep}
(在文件所在的目录中运行;echo
如果看起来不错,则删除(用于空运行))
$all
我们使用zsh
的glob 限定符按时间戳对文件列表进行排序,该限定符根据中代码返回的值oe
进行排序(数字(使用)) 。n
$REPLY
[...]
该代码使用strftime -r
(strftime
实际上是相反的strptime
)将文件名中的时间戳转换为以秒为单位的纪元时间。
然后我们循环该列表,将每个 5 字符前缀的最新文件记录到$latest
关联数组中。
然后我们使用${a:|b}
数组减法运算符删除$all
不在其中的元素$keep
(本身包含关联数组的值$latest
)。
假设*.err.*.csv
当前目录中的所有文件都采用您指定的格式,尽管它也会容纳文件名,其中日期元素用 s 分隔,-
而不是像_
某些示例中所示的 s (通过使用 ksh93-将-
s 转换为s)_
样式${var//pattern/replacement}
运算符)。