ファイル名のタイムスタンプに基づいて特定のディレクトリにファイルを移動する

ファイル名のタイムスタンプに基づいて特定のディレクトリにファイルを移動する

次の形式でcsvファイルを生成するbashスクリプトがあります。

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

YYYYmmddHHMMcsvファイルの作成時間ではなく、csvファイル自体に含まれるデータのタイムスタンプはどこにありますか?

そのため、現在のシステム時刻(csvファイルと同じ形式、つまりYYYYmmddHHMM)をファイル名のタイムスタンプと比較するbashスクリプトを作成したいと思います。

差が120分以上の場合は、ファイルをold_dataディレクトリに移動する必要があります。

2つの差が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##*_}最後まですべてを削除してください。このコマンドはファイル名からパスを削除し、ファイル名のみを保持するように設計されていますが、提供された拡張子を削除する便利なトリックもあるため、実際のタイムスタンプを取得するにはwithを使用します。_.csvbasenamebasename.csv

$ basename "${csvfile##*_}" .csv
202312290736

残りは比較的簡単です。if時差が120分以上であるか簡単に確認してください。時間を秒単位で扱うので、分を取得するには60tで割る必要があります。または、120分を7200秒(120 x 60)に変換することもできます。

if [[ $(( curr_time - csv_time )) -ge 7200 ]]; then

重要:ファイルが多いため、処理に数分または数時間かかる場合がある場合は、各ファイルはスクリプトが開始された時間と比較され続けることに注意してください。つまり、スクリプトが到着したときに120分より古いが、スクリプトが起動したときにそうでないコンテンツは移動されません。これを望まない場合は、curr_time=$(date +%s)ループ内に行を移動してファイルforごとにリセットするようにしてください。

おすすめ記事