使用日

使用日

やるべきことがあり、論理を考えることができますが、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";
}

関連情報