Why date command does not recognize my variable? [duplicate] - linux

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 3 years ago.
I'm trying to write a script that takes a timestamp (just hours, no minutes) written in a file and transforms it in seconds since Epoch, but it is failing and I don't understand why.
The script that I'm using:
#!/bin/bash
time=$(cat time.txt)
stime=$(date --date "$(echo '$time')" +%s)
echo "$stime"
Contents of time.txt
06
Output:
date: invalid date ‘$time’

Because you are single quoting the variable, so it is not being expanded to its contents. Try with double quotes, which allow expansion:
stime=$(date --date "$(echo "$time")" +%s)
BTW, I cannot see any reason to spawn a subshell to echo the variable when you can plainly give the variable to the command:
stime=$(date --date "$time" +%s)

On the command
stime=$(date --date "$(echo '$time')" +%s)
You don't need the single quotes on $time. Just use it without them
stime=$(date --date "$(echo $time)" +%s)

Related

Use bash to write a bash script? [duplicate]

This question already has answers here:
echo "#!" fails -- "event not found"
(5 answers)
Closed 7 months ago.
echo "#!/bin/bash\nls -l /home/" > /home/myscript.sh
bash: !/bin/bash\nls: event not found
My script should be:
#!/bin/bash
ls -l /home/
Why does it ignore the echo "" string and think that there is some sort of event? Why does it not recognize #!/bin/bash as a special word?
the same thing happens when I
echo "#!/bin/bash" > /home/myscript.sh
so it's not the new line!
echo -e "#\!/bin/bash" > /home/myscript.sh
writes the file content as:
#\!/bin/bash
Why is this simple action going miserably wrong?
From the bash manpage:
Enclosing characters in double quotes preserves the literal value of
all characters within the quotes, with the exception of $, `, \,
and, when history expansion is
enabled, !.
So either use single quotes, or disable history expansion with set +o history.
But don't use echo. Instead, do :
printf '%s\n' '#!/bin/bash' 'ls -l /home/' > /home/myscript
or
cat > /home/myscript << 'EOF'
#!/bin/bash
ls -l /home/
EOF
echo -e '#!/bin/bash\nls -l /home/' > /home/myscript.sh
a combination of -e and using single quote fixed it.

Date command as a variable in a bash script. Needs to be invoked each time instead of during variable declaration

I have a bash script and at certain points I am using echo to put some messages in a log file. The problem that I have is related to the DATE variable which will be static throughout the entire execution of the script.
I have this basic script below to illustrate the problem:
#!/bin/bash
DATE=`date +"%Y-%m-%dT%H:%M:%S%:z"`
echo "script started at $DATE"
echo "doing something"
sleep 2
echo "script finished at $DATE"
If I execute this script, the output of the $DATE variable is the same in both lines. Is there some bash magic that could nicely resolve this without having to replace $DATE with the command itself on each line?
Thanks in advance
Newer versions of the bash/printf builtin have support for generating datetime stamps without the need to spawn a subprocess to call date:
$ builtin printf --help
...snip...
Options:
-v var assign the output to shell variable VAR rather than
display it on the standard output
...snip...
In addition to the standard format specifications described in printf(1),
printf interprets:
%b expand backslash escape sequences in the corresponding argument
%q quote the argument in a way that can be reused as shell input
%(fmt)T output the date-time string resulting from using FMT as a format
string for strftime(3)
... snip ...
Instead of spawning a subprocess to call date, eg:
logdt=`date +"%Y-%m-%dT%H:%M:%S:%z"`
The same can be accomplished via printf -v by wrapping the desired format in %(...)T, eg:
printf -v logdt '%(%Y-%m-%dT%H:%M:%S:%z)T'
NOTE: assuming %:z should be :%z
Assuming you'll be tagging a lot of lines with datetime stamps then the savings from eliminating the subproces date calls could be huge.
Running a test of 1000 datetime stamp generations:
$ time for ((i=1;i<=1000;i++)); do { printf -v logdt '%(...)T' | logdate=$(date ...) }; done
Timings for printf -v logdt '%(...)T':
real 0m0.182s # ~130 times faster than $(date ...)
user 0m0.171s
sys 0m0.000s
Timings for logdt=$(date ...):
real 0m24.443s # ~130 times slower than printf -v
user 0m5.533s
sys 0m16.724s
With bash version 4.3+ , you can use the builtin printf to format datetimes. -1 below is a magic value that means "now".
#!/bin/bash
datefmt='%Y-%m-%dT%H:%M:%S%z'
printf "script started at %($datefmt)T\n" -1
echo "doing something"
sleep 2
printf "script finished at %($datefmt)T\n" -1
bash didn't recognize %:z for me.
This can help you:
#!/bin/bash
echo "script started at $(date +'%Y-%m-%dT%H:%M:%S%:z')"
echo "doing something"
sleep 2
echo "script finished at $(date +'%Y-%m-%dT%H:%M:%S%:z')"
You might want to create an alias if calling the full command looks clumsy to you.

shell script looping [duplicate]

This question already has answers here:
How to loop through dates using Bash?
(10 answers)
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 11 months ago.
I am new to bash scripting and trying to write a loop to run a curl command but however getting errors. Please suggest the write syntax.
#!/usr/bin/env sh
start = $1
end = $2
start=$(date -d $start +%Y-%m-%d)
end=$(date -d $end +%Y-%m-%d)
while [[ $start -le $end ]]
do
echo $start
curl -H "command, which can't be shared"
start=$(date -d"$start + 1 day" +"%Y-%m-%d")
done
The command line to run the script used sh filename.sh "2022-02-01" "2022-02-25".
However, the first error I received is windows cannot find '2022-02-01'. Make sure you typed the name correctly, and then try again.
Please suggest the errors.

How to get time since file was last modified in seconds with bash?

I need to get the time in seconds since a file was last modified. ls -l doesn't show it.
There is no simple command to get the time in seconds since a file was modified, but you can compute it from two pieces:
date +%s: the current time in seconds since the Epoch
date -r path/to/file +%s: the last modification time of the specified file in seconds since the Epoch
Use these values, you can apply simple Bash arithmetic:
lastModificationSeconds=$(date -r path/to/file +%s)
currentSeconds=$(date +%s)
((elapsedSeconds = currentSeconds - lastModificationSeconds))
You could also compute and print the elapsed seconds directly without temporary variables:
echo $(($(date +%s) - $(date -r path/to/file +%s)))
In BASH, use this for seconds since last modified:
expr `date +%s` - `stat -c %Y /home/user/my_file`
I know the tag is Linux, but the stat -c syntax doesn't work for me on OSX. This does work...
echo $(( $(date +%s) - $(stat -f%c myfile.txt) ))
And as a function to be called with the file name:
lastmod(){
echo "Last modified" $(( $(date +%s) - $(stat -f%c "$1") )) "seconds ago"
}

Better quote to execute command on shell script

I'm in doubt of the diference and which one is the better quote to execute a command in shell script.
For example, I have this two examples:
echo "The name of the computer is `uname -n`"
echo "The name of the computer is $(uname -n)"
Which one is better? Or there is no diference?
The $(...) one is generally recommended because it nests easier. Compare:
date -d "1970-01-01 $(echo "$(date +%s)-3600"|bc) sec UTC"
date -d "1970-01-01 `echo \"\`date +%s\`-3600\"|bc` sec UTC "

Resources