我有一个 bash 脚本,生成以下格式的 csv 文件:
056_log_202312290735.csv
056_log_202312290736.csv
067_dat_202312290737.csv
067_dat_202312290838.csv
056_log_202312290951.csv
067_dat_202312290952.csv
056_log_202312290953.csv
...
056_log_YYYYmmddHHMM.csv
067_dat_YYYYmmddHHMM.csv
其中YYYYmmddHHMM
是 csv 文件本身包含的数据的时间戳,而不是 csv 文件的创建时间。
所以我想编写一个bash脚本来比较当前系统时间(格式与csv文件相同,即YYYYmmddHHMM
)与文件名上的时间戳,
如果两者之间的差异大于或等于 120 分钟,则必须将文件移至old_data
目录。
如果两者之间的差异小于 120 分钟,则必须将文件移动到current_data
目录
使用当前系统时间 202312291048,必须按如下方式移动文件:
~/old_data/
056_log_202312290735.csv
056_log_202312290736.csv
067_dat_202312290737.csv
067_dat_202312290838.csv
~/current_data/
056_log_202312290951.csv
067_dat_202312290952.csv
056_log_202312290953.csv
到目前为止,我知道我可以使用我想要的格式获取当前时间:
CUR_TIME="`date +%Y%m%d%H%M`";
并使用以下命令从 csv 文件获取时间戳:
ls 056*.csv | cut -d'_' -f 3 | cut -c -12; #get timestamps from 056 files
ls 067*.csv | cut -d'_' -f 3 | cut -c -12; #get timestamps from 067 files
从那时起,我不知道如何继续前进..请帮助。
这就是我能想到的:
#!/bin/bash
CUR_TIME=$(date +%Y%m%d%H%M);
for csvfile in *.csv
do
TIME_DIFF=0
TIMESTAMP= $(echo $csvfile | cut -d'_' -f 3 | cut -c -12)
TIME_DIFF= $CUR_TIME-$TIMESTAMP
if $TIME_DIFF >= 120
then
mv -f $csvfile ~/old_data/
else
mv -f $csvfile ~/current_data/
fi
done
答案1
您不能简单地减去这样的日期戳,因为例如,202312291607(即2023/12/29 16:07)减去60是202312291547,实际上是2023/12/29 15:47,所以不是60分钟前,而是20分钟前。请记住,我们使用60 基数系统,所以我们不能按照您的建议进行简单的以 10 为底的计算。常见的解决方案是将您的时间转换为自纪元以来的秒数,然后比较它们以获得以秒为单位的差异,然后将其转换为分钟。例如:
#!/bin/bash
## Get the current time in seconds since the epoch
curr_time=$(date +%s)
for csvfile in *.csv; do
## Extract the timestamp from the csv file name.
csv_date_string=$(basename "${csvfile##*_}" .csv |
sed -E 's|(....)(..)(..)(..)(..)|\1/\2/\3 \4:\5|')
## Convert the csv datestamp to seconds since the epoch
csv_time=$( date -d "$csv_date_string" +%s)
## Compare to the current time and, if more than or equal to 120
## echo the mv command, if less, echo that we do nothing.
if [[ $(( (curr_time - csv_time) / 60)) -ge 120 ]]; then
echo mv "$csvfile" old_data
else
echo "Not moving $csvfile"
fi
done
运行上面的脚本,如果它看起来像您想要的那样工作,请删除echo
以实际运行mv
命令并移动文件。
这里的技巧是使用基本的字符串操作从文件名中提取时间戳。该语法将从字符串开头${var##pattern}
删除最长的匹配项。pattern
在这里,模式是*_
,所以一切直到 _。她正在行动:
$ csvfile=056_log_202312290736.csv
$ echo ${csvfile##*_}
202312290736.csv
因此${csvfile##*_}
删除直到最后的所有内容_
,留下 datestamp plus .csv
。该basename
命令旨在删除文件名中的路径并仅保留文件名,但它还有一个删除提供的扩展名的有用技巧,因此这就是我使用basename
with.csv
来获取实际时间戳的原因:
$ basename "${csvfile##*_}" .csv
202312290736
其余部分相对简单。简单if
检查时差是否超过120分钟。请注意,由于我处理的时间以秒为单位,因此我必须除以 60 t 才能得到分钟。或者,我可以将 120 分钟转换为 7200 秒 (120 x 60):
if [[ $(( curr_time - csv_time )) -ge 7200 ]]; then
重要的:如果您有很多文件,并且处理可能需要几分钟甚至几小时,请注意,每个文件仍将与脚本启动的时间进行比较。这意味着脚本到达时可能早于 120 分钟但脚本启动时并非如此的内容将不会被移动。如果您不想这样做,请将该curr_time=$(date +%s)
行移到循环内for
,以便为每个文件重置它。