使用日期

使用日期

我有一个任务要做,我能够想到逻辑但无法在 Unix 中实现。

我有一个目录,其中子目录的命名模式为“mmddyy”。所以我这里的任务是删除所有早于 X 天的目录。所讨论的日期戳不是 Unix 时间戳,而是通过目录名称来表示的日期戳。

我的方法:

  1. 获取数组中的目录名称列表
  2. If (SYSDATE - array > 30) then 删除 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岁以上的年份被假定为上世纪(123199指1999年12月31日,092217指2017年9月22日)。

如果您没有这些 shell,并且使用的是 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";
}

相关内容