사용 날짜

사용 날짜

해야 할 일이 있고 논리를 생각할 수 있지만 Unix에서는 구현할 수 없습니다.

이름 지정 패턴이 "mmddyy"인 하위 디렉터리가 있는 디렉터리가 있습니다. 그래서 여기서 내 임무는 X일보다 오래된 모든 디렉터리를 삭제하는 것입니다. 문제의 날짜 스탬프는 Unix 타임스탬프가 아니라 디렉터리 이름으로 표시되는 날짜 스탬프입니다.

내 접근 방식:

  1. 배열의 디렉터리 이름 목록 가져오기
  2. (SYSDATE - 배열 > 30)인 경우 Else를 삭제하고 계속합니다.

Unix를 사용하여 어떻게 해결합니까?

답변1

파일의 날짜 세부 정보를 yy-mm-dd로 다시 포맷한 다음 에포크 이후의 날짜와 초를 사용합니다.

X=30 - 30일 전

epc=$(date -d -"$X"days +%s)

epc는 확인할 참조 에포크 문자열입니다.

그런 다음 파일 이름의 날짜를 처리하십시오.

파일 이름의 날짜 예

 dat="010188" 
 dat1=awk '{print substr($0,5,2)"-"substr($0,3,2)"-"substr($0,1,2)}' <<< $dat
 refepc=$(date -d "$dat1" +%s)

refepc는 epc와 비교하여 확인할 수 있는 참조 에포크입니다.

답변2

then=$( date -d '30 days ago' +%y%m%d )

for d in *; do
    if [[ -d "$d" ]] && [[ "$d" =~ ^([0-9][0-9])([0-9][0-9])([0-9][0-9])$ ]]; then
        datestring="${BASH_REMATCH[3]}${BASH_REMATCH[1]}${BASH_REMATCH[2]}"

        if [[ "$datestring" < "$then" ]]; then
            echo rm -rf "$d"
        fi
    fi
done

스크립트는 bash먼저 GNU를 사용하여 30일 전 날짜를 계산 하고 date이를 .YYMMDD$then

그런 다음 현재 디렉터리에서 찾은 이름을 반복합니다. 발견된 이름이 주어진 정규식과 일치하는 디렉터리인 경우 디렉터리 이름의 일부를 선택 YYMMDD하고 $datestring.

$datestring사전순으로 보다 작 으면 $then해당 디렉토리를 삭제해야 합니다. 이렇게 하면 echo실제로 이런 일이 발생하는 것을 방지할 수 있으므로 삭제하기 전에 몇 번 실행하여 제대로 작동하는지 확인하세요.

시험:

$ mkdir {01..12}0117  # one directory for the 1st of every month this year
$ bash ./script.sh
rm -rf 010117
rm -rf 020117
rm -rf 030117
rm -rf 040117
rm -rf 050117
rm -rf 060117
rm -rf 070117
rm -rf 080117

(오늘 날짜는 170922이고 $then값은 170823)

지난 세기의 날짜가 포함된 디렉토리 이름의 경우 이는 확실히 실패합니다(이러한 날짜는 제거되지 않습니다).

답변3

그리고 zsh:

#! /usr/bin/env zsh
days=${1-30}

zmodload zsh/datetime || exit

strftime -s cutoff %Y%m%d $((EPOCHSECONDS - days * 24 * 60 * 60))

old_enough() {
  year=$REPLY[5,6]
  ((year += 1900 + (year < 70) * 100))
  [[ $year$REPLY[1,4] < $cutoff ]]
}

set -o extendedglob
echo rm -rf [0-9](#c6)(/+old_enough)

만족스러우면 삭제 echo하거나 파이프하세요 sh.

의 경우 ksh93해당 내용은 다음과 같습니다.

#! /usr/bin/env ksh
days=${1-30}

cutoff=$(printf '%(%Y%m%d)T' "$days days ago")

old_enough() {
  year=${1:4}
  ((year += 1900 + (year < 70) * 100))
  [[ $year${1:0:4} < $cutoff ]]
}
dirs=()
for f in {6}([0-9]); do
  [ -d "$f" ] && [ ! -L "$f" ] && old_enough "$f" && dirs+=("$f")
done
if ((${#dirs[@]})); then
  echo rm -rf "${dirs[@]}"
else
  echo >&2 "No match"
  exit 1
fi

의 경우 bash해당 내용은 다음과 같습니다.

#! /usr/bin/env bash
days=${1-30}

printf -v now '%(%s)T' -1
printf -v cutoff '%(%Y%m%d)T' "$((now - days * 24 * 60 * 60))"

old_enough() {
  year=${1:4}
  year=${year#0} # work around bug where bash complains about 08 and 09
  ((year += 1900 + (year < 70) * 100))
  [[ $year${1:0:4} < $cutoff ]]
}
shopt -s nullglob
dirs=()
for f in [0-9][0-9][0-9][0-9][0-9][0-9]; do
  [ -d "$f" ] && [ ! -L "$f" ] && old_enough "$f" && dirs+=("$f")
done
if ((${#dirs[@]})); then
  echo rm -rf "${dirs[@]}"
else
  echo >&2 "No match"
  exit 1
fi

70세 이상은 지난 세기( 1231991999년 12월 31일 기준, 0922172017년 9월 22일 기준)로 추정된다.

이러한 쉘이 없고 Unix(GNU(UNG) 아님) 시스템을 사용하는 경우 최선의 선택은 아마도 다음을 사용하는 것입니다 perl.

#! /usr/bin/env perl
use POSIX;
$cutoff = time - ($ARGV[0] // 30) * 24 * 60 * 60;
$, = " "; $\ = "\n";
if (@dirs = grep {
    /^(\d\d)(\d\d)(\d\d)$/ && ! -l && -d && 
    mktime(0,0,0,$2,$1-1,$3+100*($3<70)) < $cutoff} <*>) {
  print "rm -rf", @dirs;
} else {
  die "No match";
}

관련 정보