views:

96

answers:

3
shell>/bin/date -d "091029 20:18:02" +%s
1256827682

Similarly I created shell script:

#My.sh
myDate=`date +'%y%m%d_%H%M%S'`
myDate1=`echo $myDate | sed 's/_/ /g'`
myDate2=`echo $myDate1 | sed 's/\([0-9][0-9][0-9][0-9][0-9][0-9]\) \([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)/\/bin\/date -d "\1 \2:\3:\4" +%s/'`
print $myDate2
`$myDate2`

But it doesn't execute above command. WHy?

+4  A: 

The backticks in the last line executes the command and then executes the output of that command, which is probably not what you are trying to do -- when I run this I get the output -bash: 1256829614: command not found. Remove the backticks on the last line so that it just says

    $myDate2
mobrule
eval $myDate2 did the trick.output=`eval $myDate2`echo $output
kedar
+2  A: 

The notation:

`$myDate2`

expands $myDate2 and executes the command (and I'll come back to why there are problems with that), and then captures the output - and tries to run the output.

What you are looking for is eval:

eval $myDate2

Handling quotes is tricky - and eval is often a part of the answer. When you build up a string with internal quotes, you need to use eval to get the shell to put the quotes back together.

One very useful tool that I have is a program called al - for argument list.

#include <stdio.h>
int main(int argc, char **argv)
{
    while (*++argv != 0)
        puts(*argv);
    return(0);
}

It prints each separate argument on a separate line. It was almost the first thing I did when looking at what you are up to.

myDate=`date +'%y%m%d_%H%M%S'`
myDate1=`echo $myDate | sed 's/_/ /g'`
myDate2=`echo $myDate1 | sed 's/\([0-9][0-9][0-9][0-9][0-9][0-9]\) \([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)/\/bin\/date -d "\1 \2:\3:\4" +%s/'`
print $myDate2
#`$myDate2`
al $myDate2
eval al $myDate2
eval $myDate2

The trace output from this was:

+ date +%y%m%d_%H%M%S
+ myDate=091029_082546
+ sed 's/_/ /g'
+ echo 091029_082546
+ myDate1='091029 082546'
+ sed 's/\([0-9][0-9][0-9][0-9][0-9][0-9]\) \([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)/\/bin\/date -d "\1 \2:\3:\4" +%s/'
+ echo 091029 082546
+ myDate2='/bin/date -d "091029 08:25:46" +%s'
+ print /bin/date -d '"091029' '08:25:46"' +%s
/bin/date -d "091029 08:25:46" +%s
+ al /bin/date -d '"091029' '08:25:46"' +%s
/bin/date
-d
"091029
08:25:46"
+%s
+ eval al /bin/date -d '"091029' '08:25:46"' +%s
+ al /bin/date -d '091029 08:25:46' +%s
/bin/date
-d
091029 08:25:46
+%s
+ eval /bin/date -d '"091029' '08:25:46"' +%s
+ /bin/date -d '091029 08:25:46' +%s
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... 
            [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]

Note how when I ran 'al $myDate2' the date string was split into two arguments, but when I ran 'eval al $myDate2', the string was one argument - as required. I was testing on MacOS X, where the data command does not accept the date string format you supplied - that is a whole separate problem. But getting the string healed requires 'eval'.


I didn't even address the issue of what the shell script was trying to do.

I gather from Hai Vu's answer that we're really after the current time in seconds since the epoch; I can sort of see how that might be.

On MacOS X, that is obtained trivially:

date +'%s'

(where the single quotes really aren't needed). The MacOS X manual page also includes the example:

      date -j -f "%a %b %d %T %Z %Y" "`date`" "+%s"

This seems a bit convoluted - but would allow you to find the seconds since the epoch for any date previously given by the date command - or a date that will be given at some time in the future (by replacing the back-quoted date with the previous string).

An æon or so ago, I wrote programs 'systime' to print the current time as the number of seconds past the epoch, and also a program 'timestamp' to convert such values back into formatted dates - because none of the standard versions of the 'date' command supported such mechanisms back then (before the C standard was standard, and therefore before strftime() was widely available). I also have a program 'strptime' for converting a formatted date into a timestamp. Ah well - nice to know that the standard programs can now do it.

However, I note that the MacOS 'date' command is a superset of the POSIX standard version; I suspect that the Linux (GNU) 'date' command is a different superset of the POSIX standard, and so on for each platform.

Jonathan Leffler
+3  A: 

In addition to the solutions above, I would like to offer assistant to get to myDate2:

$ myDate=$(date +'/bin/date -d "%y%m%d %H:%M:%S" +%%s')
$ echo $myDate
/bin/date -d "091029 09:06:29" +%s
Hai Vu
This is soooo much better. All those `sed` gyrations are completely unnecessary.
Dennis Williamson
I didn't even look at what the script was really supposed to achieve; just at the mechanics of how it achieved it.
Jonathan Leffler
@Jonathan Leffler: I completely understood what you did. This post is a complement to your solution.
Hai Vu