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

如何使用bash中可用的工具生成一个范围内所有日期的列表?,bash,shell,Bash,Shell,我想下载一组以ISO-8601日期命名的文件。使用bash+gnucoreutils有没有一种简单的方法可以做到这一点?(或者使用一些技巧使wget/curl自动生成列表,但我发现这不太可能) 与此问题类似,但不限于工作日:。 我想有一种更简单的方法可以不受这个限制 也与一年有关,但不限于一年。如果您有GNU日期,您可以使用for循环: 或者一个直到循环,这次使用Bash的扩展测试[[: # with "until" d="2014-06-29" until [[ $d > 2014-07

我想下载一组以ISO-8601日期命名的文件。使用bash+gnucoreutils有没有一种简单的方法可以做到这一点?(或者使用一些技巧使wget/curl自动生成列表,但我发现这不太可能)

与此问题类似,但不限于工作日:。 我想有一种更简单的方法可以不受这个限制


也与一年有关,但不限于一年。

如果您有GNU
日期
,您可以使用
for
循环:

或者一个
直到
循环,这次使用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;
}
使用严格;
使用警告;
使用时间::件;
使用时间:秒;
使用File::Fetch;
我的($t,$end)=映射{Time::Piece->strtime($\,“%Y-%m-%d”)}@ARGV;
而($t strftime(“%F”)。.log”;
my$ff=File::Fetch->new(uri=>$url);
my$where=$ff->fetch(to=>'.');#下载到当前目录
$t+=一天;
}

Time::Piece、Time::Seconds和File::Fetch都是核心模块。使用GNU日期和bash时,可以像使用
perl wget.pl 2014-06-29 2014-07-03那样使用它:

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

我就是这样做的:

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

这将尝试从今天开始下载所有文件,直到我们得到404。

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


它接受yyyymmdd格式的日期。

如果您在macOS上,那么
date
的工作原理与GNU
date
略有不同。下面是Tom Fenech的
date
调用的一个变体,它支持GNU和Darwin:

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

为什么不把测试放在while子句中?
while[[$start-le$end]];do
我的意思是
while[[!$start>$end]];do
。前一个不起作用。第一个可以与组合使用显式日期。但我想第二个选项会更好。如果您想要ISO-8601以外的格式,可以执行
日期-d$d+“%m/%d/”
或您喜欢的任何格式字符串,而不是上面的
echo$d
行。@ijoseph感谢您的建议,我更新了我的答案以显示这一点,或者只是
brew安装coreutils
,然后使用
gdate
d=$(date -I);
while wget "http://www.example.com/$d.log"; do
    d=$(date -I -d "$d - 1 day");
done
function datelist { for dt in $(seq -w $1 $2) ; do date -d $dt +'%Y%m%d' 2>/dev/null ; done ; } 
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