根据文件名上的时间戳将文件移动到特定目录

根据文件名上的时间戳将文件移动到特定目录

我有一个 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命令旨在删除文件名中的路径并仅保留文件名,但它还有一个删除提供的扩展名的有用技巧,因此这就是我使用basenamewith.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,以便为每个文件重置它。

相关内容