Подтвердить что ты не робот

Bash: Цитирование по датам

У меня есть bash script:

array=( '2015-01-01', '2015-01-02' )

for i in "${array[@]}"
do
    python /home/user/executeJobs.py {i} &> /home/user/${i}.log
done

Теперь я хочу выполнить цикл дат, например. 2015-01-01 до 2015-01-31.

Как достичь в Bash?

Обновить:

Nice-to-have: не должно быть начато задание до завершения предыдущего запуска. В этом случае, когда executeJobs.py завершено, bash появится приглашение $.

например. могу ли я включить wait%1 в мой цикл?

4b9b3361

Ответ 1

Использование даты GNU:

d=2015-01-01
while [ "$d" != 2015-02-20 ]; do 
  echo $d
  d=$(date -I -d "$d + 1 day")
done

Обратите внимание, что поскольку для этого используется сравнение строк, для этого требуется полная ISO 8601 запись дат ребер (не удалять ведущие нули). Чтобы проверить действительные входные данные и, если возможно, принудить их к действительной форме, вы также можете использовать date:

# slightly malformed input data
input_start=2015-1-1
input_end=2015-2-23

# After this, startdate and enddate will be valid ISO 8601 dates,
# or the script will have aborted when it encountered unparseable data
# such as input_end=abcd
startdate=$(date -I -d "$input_start") || exit -1
enddate=$(date -I -d "$input_end")     || exit -1

d="$startdate"
while [ "$d" != "$enddate" ]; do 
  echo $d
  d=$(date -I -d "$d + 1 day")
done

Последнее дополнение. Чтобы проверить, что $startdate находится перед $enddate, если вы ожидаете только даты между годами 1000 и 9999, вы можете просто использовать сравнение строк следующим образом:

while [[ "$d" < "$enddate" ]]; do

Чтобы быть на самой безопасной стороне за пределами 10000 года, когда лексикографическое сравнение ломается, используйте

while [ "$(date -d "$d" +%Y%m%d)" -lt "$(date -d "$enddate" +%Y%m%d)" ]; do

Выражение $(date -d "$d" +%Y%m%d) преобразует $d в числовую форму, т.е. 2015-02-23 становится 20150223, и идея состоит в том, что даты в этой форме можно сравнивать численно.

Ответ 2

Расширение брекетинга:

for i in 2015-01-{01..31} …

Подробнее:

for i in 2015-02-{01..28} 2015-{04,06,09,11}-{01..30} 2015-{01,03,05,07,08,10,12}-{01..31} …

Доказательство:

$ echo 2015-02-{01..28} 2015-{04,06,09,11}-{01..30} 2015-{01,03,05,07,08,10,12}-{01..31} | wc -w
 365

Compact/вложенная:

$ echo 2015-{02-{01..28},{04,06,09,11}-{01..30},{01,03,05,07,08,10,12}-{01..31}} | wc -w
 365

Упорядочено, если это имеет значение:

$ x=( $(printf '%s\n' 2015-{02-{01..28},{04,06,09,11}-{01..30},{01,03,05,07,08,10,12}-{01..31}} | sort) )
$ echo "${#x[@]}"
365

Так как он неупорядочен, вы можете просто напасть на високосные годы:

$ echo {2015..2030}-{02-{01..28},{04,06,09,11}-{01..30},{01,03,05,07,08,10,12}-{01..31}} {2016..2028..4}-02-29 | wc -w
5844