shell 如何使用bash中提供的工具生成一个范围内所有日期的列表?

vof42yt1  于 2023-02-19  发布在  Shell
关注(0)|答案(5)|浏览(78)

我想下载一堆以ISO-8601日期命名的文件。有没有简单的方法可以使用bash+GNU coreutils来实现这一点?(或者使用一些技巧让wget/curl自动生成列表,但我发现这不太可能)
与此问题类似,但不限于工作日:我想有一种更简单的方法可以做到这一点,没有这个限制。
也与How to generate date range for random data on bash相关,但不限于单个年份。

ocebsuys

ocebsuys1#

如果你有GNU date,你可以在任何POSIX兼容的shell中使用for循环:

# with "for"
for i in {1..5}; do 
    # ISO 8601 (e.g. 2020-02-20) using -I
    date -I -d "2014-06-28 +$i days"

    # custom format using +
    date +%Y/%m/%d -d "2014-06-28 +$i days"
done

或者until循环,这次使用Bash的扩展测试[[

# with "until"
d="2014-06-29"
until [[ $d > 2014-07-03 ]]; do 
    echo "$d"
    d=$(date -I -d "$d + 1 day")
done

请注意,如果将条件更改为[ "$d" \> 2014-07-03 ],则sh的非古代版本也会进行词典编纂比较。
来自这些循环之一的输出:

2014-06-29
2014-06-30
2014-07-01
2014-07-02
2014-07-03

要以更可移植的方式完成相同的工作,可以使用Perl脚本:

use strict;
use warnings;
use Time::Piece;
use Time::Seconds;    
use File::Fetch;

my ($t, $end) = map { Time::Piece->strptime($_, "%Y-%m-%d") } @ARGV; 

while ($t <= $end) {
    my $url = "http://www.example.com/" . $t->strftime("%F") . ".log";
    my $ff = File::Fetch->new( uri => $url );
    my $where = $ff->fetch( to => '.' );  # download to current directory
    $t += ONE_DAY;
}

Time::Piece、Time::Seconds和File::Fetch都是核心模块,使用起来像perl wget.pl 2014-06-29 2014-07-03

jq6vz3qz

jq6vz3qz2#

使用GNU date和bash:

start=2014-12-29
end=2015-01-03
while ! [[ $start > $end ]]; do
    echo $start
    start=$(date -d "$start + 1 day" +%F)
done
2014-12-29
2014-12-30
2014-12-31
2015-01-01
2015-01-02
2015-01-03
ehxuflar

ehxuflar3#

如果你使用的是macOS,那么date的工作方式与GNU date稍有不同。下面是Tom Fenech的date调用的一个变体,它同时支持GNU和达尔文:

if [ $(uname) = 'Darwin' ]; then
    d=$(date -j -v+1d -f %Y-%m-%d $d +%Y-%m-%d)
elif [ $(uname) = 'Linux' ]; then
    d=$(date -I -d "$d + 1 day")
fi
nfs0ujit

nfs0ujit4#

我使用这个方便的函数来处理 yyyymmdd.log.gz 格式的日志文件:

function datelist { for dt in $(seq -w $1 $2) ; do date -d $dt +'%Y%m%d' 2>/dev/null ; done ; }

它接受 yyyymmdd 格式的日期。

m1m5dgzv

m1m5dgzv5#

由于我不知道确切的日期范围,只知道最后一个文件是今天的,所以我最终使用了顶部答案的变体,它从今天的日期开始,一次向后迭代一天,直到下载失败(大概是404):

d=$(date -I);
while wget "http://www.example.com/$d.log"; do
    d=$(date -I -d "$d - 1 day");
done

相关问题