J’ai un tel script bash:
array=( '2015-01-01', '2015-01-02' ) for i in "${array[@]}" do python /home/user/executeJobs.py {i} &> /home/user/${i}.log done
Maintenant, je veux parcourir une série de dates, par exemple 2015-01-01 jusqu’au 31/01/2015.
Comment réussir dans Bash?
Mise à jour :
Nice-to-have: Aucun travail ne doit être lancé avant la fin de l’exécution précédente. Dans ce cas, lorsque executeJobs.py est terminé, l’invite de commandes $
retournera.
Par exemple, pourrais-je incorporer wait%1
dans ma boucle?
En utilisant la date GNU:
d=2015-01-01 while [ "$d" != 2015-02-20 ]; do echo $d d=$(date -I -d "$d + 1 day") done
Notez que, comme cela utilise la comparaison de chaînes, cela nécessite une notation ISO 8601 complète des dates d’arête (ne supprimez pas les zéros en tête). Pour vérifier les données d’entrée valides et les contraindre à un formulaire valide si possible, vous pouvez également utiliser la 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
Un dernier ajout : Pour vérifier que $startdate
est avant $enddate
, si vous ne prévoyez que des dates comsockets entre les années 1000 et 9999, vous pouvez simplement utiliser la comparaison de chaînes comme ceci:
while [[ "$d" < "$enddate" ]]; do
Pour être au-delà de l’année 10000, quand la comparaison lexicographique se décompose, utilisez
while [ "$(date -d "$d" +%Y%m%d)" -lt "$(date -d "$enddate" +%Y%m%d)" ]; do
L'expression $(date -d "$d" +%Y%m%d)
convertit $d
en une forme numérique, c'est-à-dire que 2015-02-23
devient 20150223
et que les dates sous cette forme peuvent être comparées numériquement .
Expansion Brace :
for i in 2015-01-{01..31} …
Plus:
for i in 2015-02-{01..28} 2015-{04,06,09,11}-{01..30} 2015-{01,03,05,07,08,10,12}-{01..31} …
Preuve:
$ 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 / nested:
$ echo 2015-{02-{01..28},{04,06,09,11}-{01..30},{01,03,05,07,08,10,12}-{01..31}} | wc -w 365
Commandé, si cela compte:
$ 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
Comme il n’est pas ordonné, vous pouvez simplement attaquer les années bissextiles sur:
$ 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
J’ai eu le même problème et j’ai essayé certaines des réponses ci-dessus, peut-être qu’elles sont correctes, mais aucune de ces réponses n’a permis de déterminer ce que j’essayais de faire, en utilisant macOS. J’essayais d’itérer des dates dans le passé.
J’utilise MacOS et voici ce qui a fonctionné pour moi:
#!/bin/bash # Get the machine date newDate=$(date '+%m-%d-%y') # Set a counter variable counter=1 # Increase the counter to get back in time while [ "$newDate" != 06-01-18 ]; do echo $newDate newDate=$(date -v -${counter}d '+%m-%d-%y') counter=$((counter + 1)) done
J’espère que cela aide.
Si l’on veut faire une boucle de la date d’entrée à n’importe quelle plage ci-dessous peut être utilisé, aussi il imprimera la sortie dans le format aaaaMMdd …
#!/bin/bash in=2018-01-15 while [ "$in" != 2018-01-25 ]; do in=$(date -I -d "$in + 1 day") x=$(date -d "$in" +%Y%m%d) echo $x done