bash script code error on command output to varible

     #create LinuxScanFolders cfg file if not present
     if  -f "/var/log/VirusVault/scanvirus.cfg" ]]; then
        printf ""
     else
        printf "creating scanvirus configuration
"
        cat > /var/log/VirusVault/scanvirus.cfg <<EOL
__________scanvirus configuration__________
___________________________________________
Excluded Scan Folders
etc dev proc tmp mnt media srv .snapshots
___________________________________________
Date Time Stamp
'+%Y-%m-%d %I:%M%P'
___________________________________________
EOL
     fi

     #setup configuration lines into array
     IFS=$'
' read -d '' -r -a lines < /var/log/VirusVault/scanvirus.cfg

     printf "excluded folders: %s
" "${lines[3]}"
     printf "date time stamp : %s
" "${lines[6]}" 

     #DTS_tmp="${lines[6]}"
     Date_Time_Stamp=$(date "${lines[6]}") 
     
     #printf -v  Date_Time_Stamp "%s" "$(date "${lines[6]}")"
     printf  "%s
"  "$Date_Time_Stamp"


cfg file unchanged

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
date: invalid date ‘’+%Y-%m-%d %I:%M%P’’

change this line:
‘+%Y-%m-%d_%I:%M%P’

same results

return original line in file
‘+%Y-%m-%d %I:%M%P’

Change:
Date_Time_Stamp=date '+%Y-%m-%d %I:%M%P'

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
2020-04-24 09:49pm

Change
Date_Time_Stamp=$(date ‘+%Y-%m-%d %I:%M%P’)

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
2020-04-24 09:49pm

Change
Date_Time_Stamp=$(date ("${lines[6]}"))

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
./scanvirusa: command substitution: line 137: syntax error near unexpected token "${lines[6]}"' ./scanvirusa: command substitution: line 137: date ("${lines[6]}"))’

Change
Date_Time_Stamp="$(date “${lines[6]}”)"

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
date: invalid date ‘’+%Y-%m-%d %I:%M%P’’

Change
DTS_tmp="${lines[6]}"
Date_Time_Stamp=$(date “$DTS_tmp”)

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
date: invalid date ‘’+%Y-%m-%d %I:%M%P’’

Change
DTS_tmp="${lines[6]}"
printf "%s
" “$DTS_tmp”
Date_Time_Stamp=$(date “$DTS_tmp”)

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
‘+%Y-%m-%d %I:%M%P’
date: invalid date ‘’+%Y-%m-%d %I:%M%P’’

Change
Date_Time_Stamp=date ("${lines[6]}")

excluded folders: etc dev proc tmp mnt media srv .snapshots
date time stamp : ‘+%Y-%m-%d %I:%M%P’
./scanvirusa: command substitution: line 137: syntax error near unexpected token "${lines[6]}"' ./scanvirusa: command substitution: line 137: date ("${lines[6]}")’

This works, but I need a variable inside the command substitution. No combination of syntax will let me put a variable inside that statement in any form.

Hi,

Not sure what variables inside the command sub you’re talking. anyhow the

IFS=$'
' read -d '' -r -a lines 

Is used when you’re stuck at bashv3 (hello Mac users). Bashv4+ has mapfile aka readarray.

mapfile -t lines < file.txt

What makes you believe content of .cfg file is ever interpreted as shell script directly? Did you try to actually read code in original post?

With the double quotes above word splitting doesn’t occur.

Exactly. Now read posted code and ask yourself where ${lines[6]} variable comes from and what its content is.

Hi,

It seems you’re issue is with the ( ) when assigning the date.

date '(+%Y-%m-%d %I:%M%P)'

Output


date: invalid date ‘(+%Y-%m-%d %I:%M%P)’

var=$(date (+%Y-%m-%d %I:%M%P))

Output

bash: command substitution:  syntax error near unexpected token `+%Y-%m-%d'
bash: command substitution:  `date (+%Y-%m-%d %I:%M%P))'

Can be done with printf

Time_Date_Stamp=$(printf "(%(%Y-%m-%d %I:%M%P)T)");
echo "$Time_Date_Stamp"

Or with date command using a variable

var=$(date '+%Y-%m-%d %I:%M%P'); var="($var)"
echo "$var"

I’m not going to mention

printf -v

since you’re already using that.

I believed parameter substitution worked like a C macro, before word splitting. And I expressed how my observation differed from this belief. Not sure why you believe I made no effort to help OP though.

In fact, if we do take the line as a literal shell script, then the following command would be more correct:


Time_Date_Stamp=$(sh -c "${lines[6]}")

It does as long as you do not prohibit word splitting in the first place.

the following command would be more correct:

Time_Date_Stamp=$(sh -c “${lines[6]}”)

Time_Date_Stamp=$( ${lines[6]} )

Time_Date_Stamp=$(sh -c “${lines[6]}”)

Hi,

I just wanted to point out that POSIX sh does not have array, while

sh -c "${lines[6]}"

might work because sh is just a symlink to bash on openSUSE, while for some distro like, say Ubuntu that syntax will fail because the sh their using is a symlink to dash, just saying.

I am with you that we only have the word of the OP that he is using bash (it is prominent in his thread title). But we did not see his shebang. (The only shebang there is in this thread is from @malcolmlewis example/suggestion).

I found that readarray command and tried it. I was trying to narrow down the error by trying different lines, including use of the read command.

var1=“parm1”
command_output=$(command “$var1”)

This general structure doesn’t work as you saw. I tested every combination I could find.

I checked that before and repeated it again.

 #create LinuxScanFolders cfg file if not present
 if  -f "/var/log/VirusVault/scanvirus.cfg" ]]; then
    printf ""
 else
    printf "creating scanvirus configuration

"
cat > /var/log/VirusVault/scanvirus.cfg <<EOL
scanvirus configuration


Excluded Scan Folders
etc dev proc tmp mnt media srv .snapshots


Date Time Stamp
‘+%Y-%m-%d %I:%M%P’


EOL
fi

 
     #setup configuration lines into array
     #IFS=$'
' read -d '' -r -a lines < /var/log/VirusVault/scanvirus.cfg
     readarray -t lines < /var/log/VirusVault/scanvirus.cfg
     printf "excluded folders: %s
" "${lines[3]}"
     printf "date time stamp : %s
" "${lines[6]}" 

     #DTS_tmp="${lines[6]}"
     printf  "Lines [6]: %s
"  "${lines[6]}"
     Date_Time_Stamp=$( date "${lines[6]}" )


date time stamp : ‘+%Y-%m-%d %I:%M%P’
Lines [6]: ‘+%Y-%m-%d %I:%M%P’
date: invalid date ‘‘+%Y-%m-%d %I:%M%P’’

The results of read vs readarray are the same.

Also, the user is going to cut and paste the date time stamp they want.
This seems to work, no crash. It just needs some small fixes.

     if  -f "/var/log/VirusVault/scanvirus.cfg" ]]; then
        printf ""
     else
        printf "creating scanvirus configuration
"
        cat > /var/log/VirusVault/scanvirus.cfg <<EOL
__________scanvirus configuration__________
___________________________________________
Excluded Scan Folders
etc dev proc tmp mnt media srv .snapshots
___________________________________________
Date Time Stamp
'+%Y-%m-%d %I:%M%P'
___________________________________________
EOL
     fi

     #setup configuration lines into array
     #IFS=$'
' read -d '' -r -a lines < /var/log/VirusVault/scanvirus.cfg
     readarray -t lines < /var/log/VirusVault/scanvirus.cfg
     printf "excluded folders: %s
" "${lines[3]}"
     printf "date time stamp : %s
" "${lines[6]}" 

     #DTS_tmp="${lines[6]}"
     printf  "Lines [6]: %s
"  "${lines[6]}"
     Date_Time_Stamp=$(printf "(%("${lines[6]}")T)");
     
     #printf -v  Date_Time_Stamp "%s" "$(date "${lines[6]}")"
     printf  "%s
"  "$Date_Time_Stamp"


date time stamp : ‘+%Y-%m-%d_%I:%M%P’
Lines [6]: ‘+%Y-%m-%d_%I:%M%P’
(‘+2020-04-27_06:39pm’)

This works if you change the cfg line with no space.
‘+%Y-%m-%d_%I:%M%P’

More reading and commenting later…

Finally got to this message. :stuck_out_tongue:

 Date_Time_Stamp=$(date '+%Y-%m-%d %I:%M%P')
 printf  "%s

" $Date_Time_Stamp
printf “%s” $Date_Time_Stamp;printf "
"
printf “%s” “$Date_Time_Stamp”;printf "
"

Argument to “date” command is literal string ‘+%Y-%m-%d %I:%M%P’ including single quotes. It does not start with + so it is not valid format specification and it is obviously not valid date/time.

This is rather evolutionary approach to programming - make random changes to your code and wait for natural selection to pick up the working one. May be you should finally take a break and read about shell quoting rules.

You should know the very famous bug. The biggest pain the backside. The one that takes the longest to find. The “off by one bug” or the typos bug. Must have added that ‘+’ at some point.

However, it didn’t affect the code when I removed it. It was a much more complex problem. (see next message).

Results in more internet searching…

CFG file

Date Time Stamp
‘+%Y-%m-%d %I:%M%P’

Some user cuts and pastes the date and time stamp they want. The above should be typical. Execute the ‘date --help’ command . Then make the date they want. Then copy and paste into the cfg file.

     #setup configuration lines into array
     readarray -t lines < /var/log/VirusVault/scanvirus.cfg
     printf "excluded folders: %s
" "${lines[3]}"
     printf "date time stamp : %s
" "${lines[6]}" 
     
     date "${lines[6]}"
     
     shopt -s lastpipe
     date "${lines[6]}" | readarray -t Date_Time_Stamp
     shopt -u lastpipe
     
     printf  "%s
"  $Date_Time_Stamp
     printf "%s" $Date_Time_Stamp;printf "
"
     printf "%s" "$Date_Time_Stamp";printf "
"


date time stamp : +%Y-%m-%d %I:%M%P
2020-04-27 10:31pm
2020-04-27
10:31pm
2020-04-2710:31pm
2020-04-27 10:31pm

     #setup configuration lines into array
     readarray -t lines < /var/log/VirusVault/scanvirus.cfg
     printf "excluded folders: %s
" "${lines[3]}"
     printf "date time stamp : %s
" "${lines[6]}" 
     
     date "${lines[6]}"
     
     shopt -s lastpipe
     date "${lines[6]}" | tr ' ' '_' | readarray -t Date_Time_Stamp
     shopt -u lastpipe
     
     printf  "%s
"  $Date_Time_Stamp
     printf "%s" $Date_Time_Stamp;printf "
"
     printf "%s" "$Date_Time_Stamp";printf "
"


date time stamp : +%Y-%m-%d %I:%M%P
2020-04-27 10:32pm
2020-04-27_10:32pm
2020-04-27_10:32pm
2020-04-27_10:32pm

     #setup configuration lines into array
     readarray -t lines < /var/log/VirusVault/scanvirus.cfg
     #printf "excluded folders: %s
" "${lines[3]}"
     #printf "date time stamp : %s
" "${lines[6]}" 
     
     #date "${lines[6]}"
     
     shopt -s lastpipe
     date "${lines[6]}" | tr ' ' '_' | readarray -t Date_Time_Stamp
     shopt -u lastpipe

This enables and disables a bash function so the varible doesn’t get nulled. Also, converts spaces to underscores.

Results: No errors and no extra lines. Folder was date stamped properly. :slight_smile: (doing the victory dance)

linux_2020-04-27_10:44pm

Now that’s what I call persistance.

Thanks to who all contrubuted. Every piece helped solved this puzzle.

malcolmlewis,awerlang,arvidjaar,hcvv,Knurpht,jetchisel

Now to move on to reading the system folder line.

Glad you solved it.

Instead of lastpipe, you can use the <() redirection:

readarray -t Date_Time_Stamp < <(date '+%Y-%m-%d %I:%M%P' | tr ' ' '_')

5 minutes after I posted that message. Bash reported ‘invalid date’ again. ARG! So, I decided to redesign it using this file structure.

        printf "creating scanvirus configuration
"
        cat > /var/log/VirusVault/scanvirus.cfg <<EOL
____________________scanvirus configuration____________________
No more spaces or ' or "
Date[space]Time or Time[space]Date
_______________________________________________________________
ExcludedScanFolders= dev etc kdeinit5__0 proc tmp srv sys .snapshots
_______________________________________________________________
DateTimeStamp= +%Y-%m-%d +%I:%M:%S%P
_______________________________________________________________
EOL

The redesigned code works perfectly.

This line works from the fixed code.

shopt -s lastpipe;printf "%s" "$line" | read -a DTS_tmp;shopt -u lastpipe

This line based on yours causes scanvirus to freeze.

readarray -t Date_Time_Stamp < <(date '+%Y-%m-%d %I:%M%P' | tr ' ' '_')

readarray -t DTS_tmp < <(printf "%s" "$line")

This moving to a different subject. So, I’ll start a new topic.

The numerous date-stamp generating variations in this thread remind me of a date option I discovered recently:

▶ **date** --rfc-3339='ns'
2020-04-30 08:33:06.387416857+02:00
▶ _

Nanoseconds, baby! :wink: (In my Ruby scripts, I’ve been using these kind of timestamps for over ten years.)

It’s also a sad reminder for me that even in 2020, neither SeaMonkey nor KDE/Plasma — on which I depend daily — have left me any proper way to set ISO-8601/RFC-3339/DIN-5008 date and time formatting. Rather, the developers have been passing the buck to the underlying implementations of Gtk and Qt5, whose developers in turn point the finger to the Unicode Common Locale Data Repository (CLDR). KDE devs abandoned Mac/Windows-style date-time configurations options in favor of the incredibly slow-moving locale and CLDR-based stuff.

Meanwhile, proponents of iso8601 formatting have to live with workarounds: set en_DK.utf8 for the console locale and for KDE (Dolphin seems to be ok with it, although Gtk2 programs throw warnings — unsupported locale).

This also worked for SeaMonkey up to 2.49, but with the new 2.53.1, we’re yet again »out of luck«, as one of the SeaMonkey developers replied. Reason: adaption to the new Rust-based Firefox rendering framework, which is a great thing. Alas, setting en_DK doesn’t do the trick anymore.

After experimenting for a few days with SeaMonkey 2.53.1, the next best supported and compiled-in locale seems to be exporting LANG=en_CA.utf8 in the Seamonkey startup script (and I still have to live with that weird 12h/a.m./p.m. instead of 24h timestamps; rant over.)

Back to topic, how comparably easy indeed is setting my preferred time format in scripts I can edit and (re)write myself:

~/code ▶ **ruby** -we '10.times { t = Time.now; puts "#{t.strftime("**%F %T**")}.#{"%09d" % **t.nsec**}" }'
2020-04-30 09:07:11.381542825
2020-04-30 09:07:11.381565573
2020-04-30 09:07:11.381571005
2020-04-30 09:07:11.381597074
2020-04-30 09:07:11.381600981
2020-04-30 09:07:11.381604708
2020-04-30 09:07:11.381607953
2020-04-30 09:07:11.381611185
2020-04-30 09:07:11.381614791
2020-04-30 09:07:11.381618105
~/code ▶ _

Almost makes me wish more programs were interpreted, text-script based and easily moddable — performance be **********. Almost!