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