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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25701265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:18:37  来源:igfitidea点击:

How to generate a list of all dates in a range using the tools available in bash?

bashshell

提问by Hjulle

I want to download a bunch of files named with ISO-8601 dates. Is there a simple way to do this using bash+GNU coreutils? (Or some trick to make wget/curl to generate the list automatically, but I find that unlikely)

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

Similar to this question, but not restricted to weekdays: How to generate a range of nonweekend dates using tools available in bash?. I guess that there is a simpler way to do it without that restriction.

类似于这个问题,但不限于工作日:如何使用 bash 中可用的工具生成一系列非周末日期?. 我想有一种更简单的方法可以不受限制地做到这一点。

Also related to How to generate date range for random data on bash, but not restricted to a single year.

还与How to generate date range for random data on bash 有关,但不限于一年。

回答by Tom Fenech

If you have GNU date, you could do use either a forloop in any POSIX-compliant shell:

如果您有 GNU date,则可以在任何符合 POSIX 的 shell 中使用for循环:

# with "for"
for i in {1..5}; do 
    echo $(date -I -d "2014-06-28 +$i days")
done

or an untilloop, this time using Bash's extended test [[:

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

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

Note that non-ancient versions of shwill also do lexicographical comparison if you change the condition to [ "$d" \> 2014-07-03 ].

请注意,sh如果将条件更改为[ "$d" \> 2014-07-03 ].

Output from either of those loops:

这些循环中的任何一个的输出:

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

For a more portable way to do the same thing, you could use a Perl script:

对于做同样事情的更便携的方式,你可以使用 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 and File::Fetch are all core modules. Use it like perl wget.pl 2014-06-29 2014-07-03.

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

回答by glenn Hymanman

Using GNU date and bash:

使用 GNU 日期和 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

回答by Ernst de Haan

If you are on macOS, then dateworks a bit different from GNU date. Here's a variant to Tom Fenech's dateinvocation that supports both GNU and Darwin:

如果您使用的是 macOS,则其date工作方式与 GNU 略有不同date。这是 Tom Fenechdate调用的一个变体,它支持 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

回答by Hjulle

This is how I ended up doing it:

这就是我最终这样做的方式:

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

This tries to download all files from today's date until we get a 404.

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

回答by runlevel0

I use this handy function to work with log files in the format yyyymmdd.log.gz:

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

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

It accepts dates in the format yyyymmdd.

它接受yyyymmdd格式的日期。