我需要比较2个目录中的文件,并且能够告诉在Bash中每个文件集保持相同的时间有多长
基本上,我在不同的目录中有一组.csv文件的两个副本。一份是今天的数据,另一份是昨天的数据。我的脚本使备份每天只运行一次,所以这就是我需要运行备份的频率。我想做的是比较它们,看看文件是否相同,如果一组文件已经相同了14天,那么发送一封电子邮件通知,通知我自己和我的同事某个文件没有更改 我已经把比较部分记下来了: diff-sq DIR_1 DIR_2 | sort>comparison_results.txt 但是,现在我想读取文件,并为每一行设置一个计数器,这样我就可以知道有多少天,每组文件都是相同的,输出在不同的列中 理想情况下,这3列应该是$name_of|u file |文件是否相同?|他们有多少天是一样的 我已经开始了一个while循环来阅读每一行,但我不确定如何进行: 读行时;做我需要比较2个目录中的文件,并且能够告诉在Bash中每个文件集保持相同的时间有多长,bash,comparison,Bash,Comparison,基本上,我在不同的目录中有一组.csv文件的两个副本。一份是今天的数据,另一份是昨天的数据。我的脚本使备份每天只运行一次,所以这就是我需要运行备份的频率。我想做的是比较它们,看看文件是否相同,如果一组文件已经相同了14天,那么发送一封电子邮件通知,通知我自己和我的同事某个文件没有更改 我已经把比较部分记下来了: diff-sq DIR_1 DIR_2 | sort>comparison_results.txt 但是,现在我想读取文件,并为每一行设置一个计数器,这样我就可以知道有多少天,每组文件都
counter=0
if [[ $line == *"not identical"* ]]
then
$something
else
(( counter += 1 ))
$something_else
done < comparison_results.txt
计数器=0
如果[[$line==*“不相同”*]]
然后
美元左右
其他的
((计数器+=1))
$还有别的吗
完成
如有必要,我可以将所有这些输出写入一个文件,然后读取该文件,如果计数器列有14秒或更高,则发送电子邮件通知
基本上,我的问题是如何阅读每一行并将其发送到一个包含3列的文件中,如果其中任何一个文件已经相同了14天或更长时间,则发送电子邮件通知?这里是一个用于此目的的函数的大致草案。请注意,我只写了超过
minAge
秒的相同文件的名称(以eval
-安全引用的形式)——发送电子邮件是读者的练习
findConsistentlyIdenticalFiles() {
local dirA=$1 dirB=$2 storeLoc=$3 minAge=$4
local fnA fnB fnStore fn currentTime storedTime
mkdir -p -- "$storeLoc" || return
# in very new bash, faster alternative is: printf -v currentTime '%(%s)T' -1
# ...the following command using date is the older/slower/compatible alternative:
currentTime=$(date +%s)
# for each file in dirA...
while IFS= read -r -d '' fnA; do
# strip the directory name...
fn="${fnA#$dirA}"; fn="${fn#/}"
# and calculate the name of a corresponding file in dirB
fnB=${dirB}/${fn}
# if a file in dirA doesn't exist in dirB, or the dirB copy differs, clear our flag
if [[ ! -e $fnB ]] || ! cmp -s "$fnA" "$fnB"; then
rm -f -- "$storeLoc/$fn"
continue
fi
fnStore=$storeLoc/$fn
if [[ -e $fnStore ]]; then
# if we already have a marker, check whether it's over minAge seconds old
storedTime=$(<"$fnStore")
if (( storedTime < currentTime - minAge )); then
printf '%q\n' "$fn"
fi
else
# whereas if we don't have a marker, populate it with the current time
mkdir -p -- "${fnStore%/*}"
printf '%s\n' "$currentTime" >"$storeLoc/$fn"
fi
done < <(find "$dirA" -type f -print0)
# ...also, prune any store contents that don't have corresponding dirA contents
while IFS= read -r -d '' fnStore; do
fn="${fnStore#$storeLoc}"; fn="${fn#/}"
[[ -e $dirA/$fn ]] || rm -f -- "$fnStore"
done < <(find "$storeLoc" -type f -print0)
}
显然,您可以使用更少的秒数来轻松测试逻辑(60
查找最后一分钟未修改的相同文件,5
查找最后5秒的相同文件,等等)
一些注意事项:
- 使用
发出一个NUL分隔的文件名列表,并且find-print0
从这样一个NUL分隔的列表中读取一个名称。即使使用非常不寻常甚至恶意的名称,也可以保证正确解析此格式—带有换行符的名称,包含类似IFS=read-r-d”filename
output的字符串的名称,等等。请参阅和diff-sq
<…但是如果你有一个实际的问题,我建议你试着把它提取出来,让它更清楚。另外,特别是个人,顺便说一下,我会考虑在时间段中跟踪一个时间戳,这是第一次观察到两个文件是相同的,并且只是检查当时间戳大于(14×3600)秒之前的情况。这样你就不用处理计数器了,你的脚本可以在同一天内重新运行很多次,而不会破坏逻辑(类似地,跳过一天也不会破坏逻辑,等等)。我编辑了这篇文章来帮助澄清这个问题。我只需要脚本一天运行一次,所以我不确定是否需要时间戳。当然,除非这比柜台更容易处理。从操作角度来看,当然更容易处理。如果您有一个停机或停机窗口,并且您的系统当天错过了它的cronjob,那么您不希望所有的计数都被取消。如果您修复了一个bug,并且希望在修复该bug的情况下重新运行,那么您不希望事情增加两次。作为一个从事这一行业有一段时间的人来说,从减少头痛的角度来看,使脚本幂等通常是一个很好的实践。我会用Qt编写它,因为它有更多更高级的工具,可以用来快速、轻松地编写解决方案
QDirIterator
,QBuffer
,QTextStream
和QSqlite
是解决此问题的一些工具。。但是如果你的系统已经安装了QtQFileInfo
findConsistentlyIdenticalFiles dirA dirB .cmptimes "$(( 3600 * 14 ))"