파일 이름의 타임스탬프를 기준으로 특정 디렉터리로 파일 이동

파일 이름의 타임스탬프를 기준으로 특정 디렉터리로 파일 이동

다음 형식으로 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디렉터리로 이동해야 합니다.

둘 사이의 차이가 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각 파일에 대해 재설정되도록 하세요.

관련 정보