Calculate date/time difference form entries in two files in bash script

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












0














I have two files (STARTED and COMPLETED) that look like this:



STARTED FILE:



2018-01-30 10:21:41
2018-01-17 12:22:50
2018-06-27 23:09:20
INVALID
INVALID
... for 800 Rows


COMPLETED FILE:



2018-01-30 10:23:54
2018-01-17 13:23:45
2018-06-28 06:10:56
INVALID
INVALID
... for 800 rows


I need to create a third file that has the result of difference of each row for file2 and file1 - to get the time lapse.



NEW 3rd FILE:



00:02:13
01:00:55
07:01:36
INVALID //Where any instance of invalid in either file remain in the new file.
INVALID


... for 800 rows



I was able to get this to work manual using this command but no luck looping through my file:



string1="10:21:41"
string2="10:23:54"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

> 00:02:13









share|improve this question























  • THANKS SO MUCH SouravGosh! This worked PERFECTLY using base system utilities!
    – SSDdude
    Dec 21 '18 at 13:18















0














I have two files (STARTED and COMPLETED) that look like this:



STARTED FILE:



2018-01-30 10:21:41
2018-01-17 12:22:50
2018-06-27 23:09:20
INVALID
INVALID
... for 800 Rows


COMPLETED FILE:



2018-01-30 10:23:54
2018-01-17 13:23:45
2018-06-28 06:10:56
INVALID
INVALID
... for 800 rows


I need to create a third file that has the result of difference of each row for file2 and file1 - to get the time lapse.



NEW 3rd FILE:



00:02:13
01:00:55
07:01:36
INVALID //Where any instance of invalid in either file remain in the new file.
INVALID


... for 800 rows



I was able to get this to work manual using this command but no luck looping through my file:



string1="10:21:41"
string2="10:23:54"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

> 00:02:13









share|improve this question























  • THANKS SO MUCH SouravGosh! This worked PERFECTLY using base system utilities!
    – SSDdude
    Dec 21 '18 at 13:18













0












0








0







I have two files (STARTED and COMPLETED) that look like this:



STARTED FILE:



2018-01-30 10:21:41
2018-01-17 12:22:50
2018-06-27 23:09:20
INVALID
INVALID
... for 800 Rows


COMPLETED FILE:



2018-01-30 10:23:54
2018-01-17 13:23:45
2018-06-28 06:10:56
INVALID
INVALID
... for 800 rows


I need to create a third file that has the result of difference of each row for file2 and file1 - to get the time lapse.



NEW 3rd FILE:



00:02:13
01:00:55
07:01:36
INVALID //Where any instance of invalid in either file remain in the new file.
INVALID


... for 800 rows



I was able to get this to work manual using this command but no luck looping through my file:



string1="10:21:41"
string2="10:23:54"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

> 00:02:13









share|improve this question















I have two files (STARTED and COMPLETED) that look like this:



STARTED FILE:



2018-01-30 10:21:41
2018-01-17 12:22:50
2018-06-27 23:09:20
INVALID
INVALID
... for 800 Rows


COMPLETED FILE:



2018-01-30 10:23:54
2018-01-17 13:23:45
2018-06-28 06:10:56
INVALID
INVALID
... for 800 rows


I need to create a third file that has the result of difference of each row for file2 and file1 - to get the time lapse.



NEW 3rd FILE:



00:02:13
01:00:55
07:01:36
INVALID //Where any instance of invalid in either file remain in the new file.
INVALID


... for 800 rows



I was able to get this to work manual using this command but no luck looping through my file:



string1="10:21:41"
string2="10:23:54"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

> 00:02:13






bash rhel timestamps






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 19 '18 at 15:12









SouravGhosh

493311




493311










asked Dec 19 '18 at 14:39









SSDdude

767




767











  • THANKS SO MUCH SouravGosh! This worked PERFECTLY using base system utilities!
    – SSDdude
    Dec 21 '18 at 13:18
















  • THANKS SO MUCH SouravGosh! This worked PERFECTLY using base system utilities!
    – SSDdude
    Dec 21 '18 at 13:18















THANKS SO MUCH SouravGosh! This worked PERFECTLY using base system utilities!
– SSDdude
Dec 21 '18 at 13:18




THANKS SO MUCH SouravGosh! This worked PERFECTLY using base system utilities!
– SSDdude
Dec 21 '18 at 13:18










4 Answers
4






active

oldest

votes


















3














as oneliner



while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s")); printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));else echo INVALID; fi; done < startedfile 3<finishedfile


as a script



#!/bin/bash

while read -r StartDate && read -r FinalDate <&3; do
if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s"));
printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));
else
echo INVALID;
fi;
done < startedfile 3<finishedfile


It will give output like this:



0d:0h:2m:13s
0d:1h:0m:55s
INVALID
0d:7h:1m:36s
INVALID
INVALID


you can then just output that to file you want.




EDIT



As suggested in the comments, this can be simplified by installing dateutils package and using datediff command.



while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";else echo INVALID; fi; done < started.txt 3<finished.txt 


In a script



#!/bin/bash

while read -r StartDate && read -r FinalDate <&3; do
if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";
else
echo INVALID;
fi;
done < startedfile 3<finishedfile





share|improve this answer


















  • 1




    As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
    – Fiximan
    Dec 19 '18 at 16:04


















0














I believe I was able to solve your problem with the following bash script:



#!/usr/bin/env bash

sfile=/path/to/start
efile=/path/to/end
ofile=/path/to/out
n=0

while read -r line; do
((n++))
if [[ $line == 'INVALID' ]]; then
echo "INVALID"
continue
fi
start=$(date -u -d "$line" "+%s")
end=$(date -u -d "$(sed -n "$np" "$efile")" "+%s")
date -u -d "0 $end sec - $start sec" +"%H:%M:%S"
done<"$sfile" >"$ofile"


This will read each line of the start file and compare it to the matching line in the end file. If the line contains "INVALID" it will echo "INVALID" and skip to the next iteration of the loop.






share|improve this answer






















  • With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
    – Kusalananda
    Dec 19 '18 at 17:38


















0














Using ddiff from GNU dateutils, and bash:



#!/bin/bash

paste STARTED COMPLETED |
while IFS=$'t' read start compl; do
if [ "$start" = "INVALID" ] || [ "$compl" = "INVALID" ]; then
echo 'INVALID'
else
ddiff -f '%0H:%0M:%0S' "$start" "$compl"
fi
done


Assuming the input files are called STARTED and COMPLETED, this creates a tab-delimited input to the while loop with the start times in the first field and the completion times in the second field. It reads these and checks whether any of the two times are INVALID. If not, it calls ddiff with them.



The output of this could be saved to a file with a redirection after done at the end, or after the script name on the command line when invoking the script.



Running it on the supplied data:



$ bash script.sh
00:02:13
01:00:55
07:01:36
INVALID
INVALID





share|improve this answer






























    0














    With zsh:



    #! /bin/zsh -
    # usage: that-script file1 file2
    zmodload zsh/datetime
    while
    IFS= read -ru3 a &&
    IFS= read -ru4 b
    do
    if
    strftime -rs at '%Y-%m-%d %H:%M:%S' "$a" 2> /dev/null &&
    strftime -rs bt '%Y-%m-%d %H:%M:%S' "$b" 2> /dev/null
    then
    d=$((bt - at))
    printf '%02d:%02d:%02dn' $((d/3600)) $(((d/60)%60)) $((d%60))
    else
    printf '%sn' $a
    fi
    done 3< $1? 4< $2?


    That's still using a shell loop to process text which is generally considered bad practice but at least here we're only using builtin commands which means performance is not going to be as dreadful as if you were invoking two external GNU date commands for each line of input.






    share|improve this answer






















      Your Answer








      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "106"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f489935%2fcalculate-date-time-difference-form-entries-in-two-files-in-bash-script%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      as oneliner



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s")); printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));else echo INVALID; fi; done < startedfile 3<finishedfile


      as a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s"));
      printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile


      It will give output like this:



      0d:0h:2m:13s
      0d:1h:0m:55s
      INVALID
      0d:7h:1m:36s
      INVALID
      INVALID


      you can then just output that to file you want.




      EDIT



      As suggested in the comments, this can be simplified by installing dateutils package and using datediff command.



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";else echo INVALID; fi; done < started.txt 3<finished.txt 


      In a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile





      share|improve this answer


















      • 1




        As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
        – Fiximan
        Dec 19 '18 at 16:04















      3














      as oneliner



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s")); printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));else echo INVALID; fi; done < startedfile 3<finishedfile


      as a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s"));
      printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile


      It will give output like this:



      0d:0h:2m:13s
      0d:1h:0m:55s
      INVALID
      0d:7h:1m:36s
      INVALID
      INVALID


      you can then just output that to file you want.




      EDIT



      As suggested in the comments, this can be simplified by installing dateutils package and using datediff command.



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";else echo INVALID; fi; done < started.txt 3<finished.txt 


      In a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile





      share|improve this answer


















      • 1




        As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
        – Fiximan
        Dec 19 '18 at 16:04













      3












      3








      3






      as oneliner



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s")); printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));else echo INVALID; fi; done < startedfile 3<finishedfile


      as a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s"));
      printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile


      It will give output like this:



      0d:0h:2m:13s
      0d:1h:0m:55s
      INVALID
      0d:7h:1m:36s
      INVALID
      INVALID


      you can then just output that to file you want.




      EDIT



      As suggested in the comments, this can be simplified by installing dateutils package and using datediff command.



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";else echo INVALID; fi; done < started.txt 3<finished.txt 


      In a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile





      share|improve this answer














      as oneliner



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s")); printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));else echo INVALID; fi; done < startedfile 3<finishedfile


      as a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      diff=$(expr $(date -d "$FinalDate" +"%s") - $(date -d "$StartDate" +"%s"));
      printf '%dd:%dh:%dm:%dsn' $(($diff/86400)) $(($diff%86400/3600)) $(($diff%3600/60)) $(($diff%60));
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile


      It will give output like this:



      0d:0h:2m:13s
      0d:1h:0m:55s
      INVALID
      0d:7h:1m:36s
      INVALID
      INVALID


      you can then just output that to file you want.




      EDIT



      As suggested in the comments, this can be simplified by installing dateutils package and using datediff command.



      while read -r StartDate && read -r FinalDate <&3; do if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";else echo INVALID; fi; done < started.txt 3<finished.txt 


      In a script



      #!/bin/bash

      while read -r StartDate && read -r FinalDate <&3; do
      if [[ $StartDate != "INVALID" && $FinalDate != "INVALID" ]]; then
      datediff "$StartDate" "$FinalDate" -f "%dd:%Hh:%Mm:%Ss";
      else
      echo INVALID;
      fi;
      done < startedfile 3<finishedfile






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 19 '18 at 16:24

























      answered Dec 19 '18 at 15:36









      rAlen

      845510




      845510







      • 1




        As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
        – Fiximan
        Dec 19 '18 at 16:04












      • 1




        As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
        – Fiximan
        Dec 19 '18 at 16:04







      1




      1




      As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
      – Fiximan
      Dec 19 '18 at 16:04




      As simplification, I'd suggest using ddiff from the dateutils package which allows subtracting date strings directly: dateutils.ddiff "$startdate" "$enddate" gives the difference in seconds or a format defined by e.g. -f %H:%M:%S, i.e. matching date's formatting system.
      – Fiximan
      Dec 19 '18 at 16:04













      0














      I believe I was able to solve your problem with the following bash script:



      #!/usr/bin/env bash

      sfile=/path/to/start
      efile=/path/to/end
      ofile=/path/to/out
      n=0

      while read -r line; do
      ((n++))
      if [[ $line == 'INVALID' ]]; then
      echo "INVALID"
      continue
      fi
      start=$(date -u -d "$line" "+%s")
      end=$(date -u -d "$(sed -n "$np" "$efile")" "+%s")
      date -u -d "0 $end sec - $start sec" +"%H:%M:%S"
      done<"$sfile" >"$ofile"


      This will read each line of the start file and compare it to the matching line in the end file. If the line contains "INVALID" it will echo "INVALID" and skip to the next iteration of the loop.






      share|improve this answer






















      • With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
        – Kusalananda
        Dec 19 '18 at 17:38















      0














      I believe I was able to solve your problem with the following bash script:



      #!/usr/bin/env bash

      sfile=/path/to/start
      efile=/path/to/end
      ofile=/path/to/out
      n=0

      while read -r line; do
      ((n++))
      if [[ $line == 'INVALID' ]]; then
      echo "INVALID"
      continue
      fi
      start=$(date -u -d "$line" "+%s")
      end=$(date -u -d "$(sed -n "$np" "$efile")" "+%s")
      date -u -d "0 $end sec - $start sec" +"%H:%M:%S"
      done<"$sfile" >"$ofile"


      This will read each line of the start file and compare it to the matching line in the end file. If the line contains "INVALID" it will echo "INVALID" and skip to the next iteration of the loop.






      share|improve this answer






















      • With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
        – Kusalananda
        Dec 19 '18 at 17:38













      0












      0








      0






      I believe I was able to solve your problem with the following bash script:



      #!/usr/bin/env bash

      sfile=/path/to/start
      efile=/path/to/end
      ofile=/path/to/out
      n=0

      while read -r line; do
      ((n++))
      if [[ $line == 'INVALID' ]]; then
      echo "INVALID"
      continue
      fi
      start=$(date -u -d "$line" "+%s")
      end=$(date -u -d "$(sed -n "$np" "$efile")" "+%s")
      date -u -d "0 $end sec - $start sec" +"%H:%M:%S"
      done<"$sfile" >"$ofile"


      This will read each line of the start file and compare it to the matching line in the end file. If the line contains "INVALID" it will echo "INVALID" and skip to the next iteration of the loop.






      share|improve this answer














      I believe I was able to solve your problem with the following bash script:



      #!/usr/bin/env bash

      sfile=/path/to/start
      efile=/path/to/end
      ofile=/path/to/out
      n=0

      while read -r line; do
      ((n++))
      if [[ $line == 'INVALID' ]]; then
      echo "INVALID"
      continue
      fi
      start=$(date -u -d "$line" "+%s")
      end=$(date -u -d "$(sed -n "$np" "$efile")" "+%s")
      date -u -d "0 $end sec - $start sec" +"%H:%M:%S"
      done<"$sfile" >"$ofile"


      This will read each line of the start file and compare it to the matching line in the end file. If the line contains "INVALID" it will echo "INVALID" and skip to the next iteration of the loop.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 19 '18 at 16:12

























      answered Dec 19 '18 at 15:36









      Jesse_b

      11.9k23064




      11.9k23064











      • With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
        – Kusalananda
        Dec 19 '18 at 17:38
















      • With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
        – Kusalananda
        Dec 19 '18 at 17:38















      With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
      – Kusalananda
      Dec 19 '18 at 17:38




      With GNU date you can get it to read dates from a file with -f. This means that you could potentially get away with just one or two invocations of date instead of 800.
      – Kusalananda
      Dec 19 '18 at 17:38











      0














      Using ddiff from GNU dateutils, and bash:



      #!/bin/bash

      paste STARTED COMPLETED |
      while IFS=$'t' read start compl; do
      if [ "$start" = "INVALID" ] || [ "$compl" = "INVALID" ]; then
      echo 'INVALID'
      else
      ddiff -f '%0H:%0M:%0S' "$start" "$compl"
      fi
      done


      Assuming the input files are called STARTED and COMPLETED, this creates a tab-delimited input to the while loop with the start times in the first field and the completion times in the second field. It reads these and checks whether any of the two times are INVALID. If not, it calls ddiff with them.



      The output of this could be saved to a file with a redirection after done at the end, or after the script name on the command line when invoking the script.



      Running it on the supplied data:



      $ bash script.sh
      00:02:13
      01:00:55
      07:01:36
      INVALID
      INVALID





      share|improve this answer



























        0














        Using ddiff from GNU dateutils, and bash:



        #!/bin/bash

        paste STARTED COMPLETED |
        while IFS=$'t' read start compl; do
        if [ "$start" = "INVALID" ] || [ "$compl" = "INVALID" ]; then
        echo 'INVALID'
        else
        ddiff -f '%0H:%0M:%0S' "$start" "$compl"
        fi
        done


        Assuming the input files are called STARTED and COMPLETED, this creates a tab-delimited input to the while loop with the start times in the first field and the completion times in the second field. It reads these and checks whether any of the two times are INVALID. If not, it calls ddiff with them.



        The output of this could be saved to a file with a redirection after done at the end, or after the script name on the command line when invoking the script.



        Running it on the supplied data:



        $ bash script.sh
        00:02:13
        01:00:55
        07:01:36
        INVALID
        INVALID





        share|improve this answer

























          0












          0








          0






          Using ddiff from GNU dateutils, and bash:



          #!/bin/bash

          paste STARTED COMPLETED |
          while IFS=$'t' read start compl; do
          if [ "$start" = "INVALID" ] || [ "$compl" = "INVALID" ]; then
          echo 'INVALID'
          else
          ddiff -f '%0H:%0M:%0S' "$start" "$compl"
          fi
          done


          Assuming the input files are called STARTED and COMPLETED, this creates a tab-delimited input to the while loop with the start times in the first field and the completion times in the second field. It reads these and checks whether any of the two times are INVALID. If not, it calls ddiff with them.



          The output of this could be saved to a file with a redirection after done at the end, or after the script name on the command line when invoking the script.



          Running it on the supplied data:



          $ bash script.sh
          00:02:13
          01:00:55
          07:01:36
          INVALID
          INVALID





          share|improve this answer














          Using ddiff from GNU dateutils, and bash:



          #!/bin/bash

          paste STARTED COMPLETED |
          while IFS=$'t' read start compl; do
          if [ "$start" = "INVALID" ] || [ "$compl" = "INVALID" ]; then
          echo 'INVALID'
          else
          ddiff -f '%0H:%0M:%0S' "$start" "$compl"
          fi
          done


          Assuming the input files are called STARTED and COMPLETED, this creates a tab-delimited input to the while loop with the start times in the first field and the completion times in the second field. It reads these and checks whether any of the two times are INVALID. If not, it calls ddiff with them.



          The output of this could be saved to a file with a redirection after done at the end, or after the script name on the command line when invoking the script.



          Running it on the supplied data:



          $ bash script.sh
          00:02:13
          01:00:55
          07:01:36
          INVALID
          INVALID






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 19 '18 at 16:27

























          answered Dec 19 '18 at 16:20









          Kusalananda

          121k16229372




          121k16229372





















              0














              With zsh:



              #! /bin/zsh -
              # usage: that-script file1 file2
              zmodload zsh/datetime
              while
              IFS= read -ru3 a &&
              IFS= read -ru4 b
              do
              if
              strftime -rs at '%Y-%m-%d %H:%M:%S' "$a" 2> /dev/null &&
              strftime -rs bt '%Y-%m-%d %H:%M:%S' "$b" 2> /dev/null
              then
              d=$((bt - at))
              printf '%02d:%02d:%02dn' $((d/3600)) $(((d/60)%60)) $((d%60))
              else
              printf '%sn' $a
              fi
              done 3< $1? 4< $2?


              That's still using a shell loop to process text which is generally considered bad practice but at least here we're only using builtin commands which means performance is not going to be as dreadful as if you were invoking two external GNU date commands for each line of input.






              share|improve this answer



























                0














                With zsh:



                #! /bin/zsh -
                # usage: that-script file1 file2
                zmodload zsh/datetime
                while
                IFS= read -ru3 a &&
                IFS= read -ru4 b
                do
                if
                strftime -rs at '%Y-%m-%d %H:%M:%S' "$a" 2> /dev/null &&
                strftime -rs bt '%Y-%m-%d %H:%M:%S' "$b" 2> /dev/null
                then
                d=$((bt - at))
                printf '%02d:%02d:%02dn' $((d/3600)) $(((d/60)%60)) $((d%60))
                else
                printf '%sn' $a
                fi
                done 3< $1? 4< $2?


                That's still using a shell loop to process text which is generally considered bad practice but at least here we're only using builtin commands which means performance is not going to be as dreadful as if you were invoking two external GNU date commands for each line of input.






                share|improve this answer

























                  0












                  0








                  0






                  With zsh:



                  #! /bin/zsh -
                  # usage: that-script file1 file2
                  zmodload zsh/datetime
                  while
                  IFS= read -ru3 a &&
                  IFS= read -ru4 b
                  do
                  if
                  strftime -rs at '%Y-%m-%d %H:%M:%S' "$a" 2> /dev/null &&
                  strftime -rs bt '%Y-%m-%d %H:%M:%S' "$b" 2> /dev/null
                  then
                  d=$((bt - at))
                  printf '%02d:%02d:%02dn' $((d/3600)) $(((d/60)%60)) $((d%60))
                  else
                  printf '%sn' $a
                  fi
                  done 3< $1? 4< $2?


                  That's still using a shell loop to process text which is generally considered bad practice but at least here we're only using builtin commands which means performance is not going to be as dreadful as if you were invoking two external GNU date commands for each line of input.






                  share|improve this answer














                  With zsh:



                  #! /bin/zsh -
                  # usage: that-script file1 file2
                  zmodload zsh/datetime
                  while
                  IFS= read -ru3 a &&
                  IFS= read -ru4 b
                  do
                  if
                  strftime -rs at '%Y-%m-%d %H:%M:%S' "$a" 2> /dev/null &&
                  strftime -rs bt '%Y-%m-%d %H:%M:%S' "$b" 2> /dev/null
                  then
                  d=$((bt - at))
                  printf '%02d:%02d:%02dn' $((d/3600)) $(((d/60)%60)) $((d%60))
                  else
                  printf '%sn' $a
                  fi
                  done 3< $1? 4< $2?


                  That's still using a shell loop to process text which is generally considered bad practice but at least here we're only using builtin commands which means performance is not going to be as dreadful as if you were invoking two external GNU date commands for each line of input.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 19 '18 at 17:27

























                  answered Dec 19 '18 at 17:12









                  Stéphane Chazelas

                  299k54564913




                  299k54564913



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Unix & Linux Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f489935%2fcalculate-date-time-difference-form-entries-in-two-files-in-bash-script%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown






                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Displaying single band from multi-band raster using QGIS

                      How many registers does an x86_64 CPU actually have?