scripting help, variables not working

Hello all. I’m working on my scanvirus shell script for clam anti-virus. I can’t get this to work.

OPENSUSE - KDE

Note: not a real path, just a sample to make the point.

scanvirus_mswin1= "/pathto/mswin/drive/";

Error: “this is a directory”. Yes, is it a directory path string. Not a directory path command.

set scanvirus_mswin1= "/pathto/mswin/drive/";

I got this through a web search. This has no error, but makes a blank string.

This is the complete sequence in context.


scanvirus_mswin1= "";
scanvirus_mswin2= "";
scanvirus_mswin3= "";
scanvirus_mswin4= "";
scanvirus_mswin5= "";

if [scanvirus_mswin1 != ""]
clamscan -r "$scanvirus_mswin1";
fi

if [scanvirus_mswin2 != ""]
clamscan -r "$scanvirus_mswin2";
fi

if [scanvirus_mswin3 != ""]
clamscan -r "$scanvirus_mswin3";
fi

if [scanvirus_mswin4 != ""]
clamscan -r "$scanvirus_mswin4";
fi

if [scanvirus_mswin5 != ""]
clamscan -r "$scanvirus_mswin5";
fi

Well, that’s an easy one… :wink:

Remove the space between the = and the value, space is a separator.

And the trailing ‘;’ is not needed either, you only need ‘;’ if you want to specify more than one command in a line.

So it should look like this:

scanvirus_mswin1="/pathto/mswin/drive/"

Btw, your if statements won’t work either.
They should look like this:


if  scanvirus_mswin1 != "" ]; then
clamscan -r "$scanvirus_mswin1"
fi

or


if  scanvirus_mswin1 != "" ]
then clamscan -r "$scanvirus_mswin1"
fi

The examples you found were apparantly intended for another shell than the default (in openSUSE) bash…

On Mon, 30 Mar 2015 21:06:01 +0000, lord valarian wrote:

> Hello all. I’m working on my scanvirus shell script for clam
> anti-virus. I can’t get this to work.

Show us the script and the input/output from the commands - you’ve not
really done that, so it’s difficult to understand what it is that you’re
trying to accomplish and how the script is used.

It’s also not clear what scripting language you’re using without the
actual script (pasted inside code blocks, please - # button in the
advanced editor).

Jim


Jim Henderson
openSUSE Forums Administrator
Forum Use Terms & Conditions at http://tinyurl.com/openSUSE-T-C

Thanks, i’ll test this soon. If anything else is wrong, tell me.

#!/bin/bash 
#: Title       : scanvirus
#: Date Created: Thu Sep 2 19:27:00 PST 2010 
#: Last Edit   : Mon Mar 30 3:00:00 PST 2015
#: Author      : Lord Valarian #: Version     : 2.0.0
#: Description : Run virus scanning application 
#: Options     : p1: -windows -linux --setup --kdeicons



Create_KDE_linux_scan_icon() {
  cat > ScanVirus_KDE_Linux_Scan.desktop <<EOF
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment[en_US]=
Comment=
Exec=sh scanvirus -linux
GenericName[en_US]=
GenericName=
Icon=kde
MimeType=
Name[en_US]=ScanVirus - linux anti-virus scan
Name=ScanVirus - linux anti-virus scan
Path=$PATH
StartupNotify=true
Terminal=true
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=
X-KDE-SubstituteUID=false
X-KDE-Username=
X-SuSE-translate=trueEOF
EOF

#set file permissions
chmod 744 ScanVirus_KDE_Linux_Scan.desktop
}


Create_KDE_windows_scan_icon() {
  cat > ScanVirus_KDE_Windows_Scan.desktop <<EOF
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment[en_US]=
Comment=
Exec=sh scanvirus -mswin
GenericName[en_US]=
GenericName=
Icon=kde
MimeType=
Name[en_US]=ScanVirus - windows anti-virus scan
Name=ScanVirus - windows anti-virus scan
Path=$PATH
StartupNotify=true
Terminal=true
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=
X-KDE-SubstituteUID=false
X-KDE-Username=
X-SuSE-translate=true
EOF

#set file permissions
chmod 744 ScanVirus_KDE_Windows_Scan.desktop
}

#pwd

##############################
# shortcut code for clamscan #
############################## 
    if  $1 == "-mswin" ] ||  $1 == "-w" ]; then

          #In KDE, right-click, click on edit and copy and paste the adress for each MSWIN drive you want to scan in the quotes       
          #scanvirus_mswin1="/pathto/mswin/drive/"
          scanvirus_mswin1=""
          scanvirus_mswin2=""
          scanvirus_mswin3=""
          scanvirus_mswin4=""
          scanvirus_mswin5=""

          echo "scanvirus mswin"
          echo "---------------"

          if  scanvirus_mswin1 != "" ]; then
            echo "$scanvirus_mswin1"
            clamscan -r "$scanvirus_mswin1" -i
            echo ""
          fi

          if  scanvirus_mswin2 != "" ]; then
            echo "$scanvirus_mswin2";
            clamscan -r "$scanvirus_mswin2" -i 
            echo ""
          fi

          if  scanvirus_mswin3 != "" ]; then
            echo "$scanvirus_mswin3";
            clamscan -r "$scanvirus_mswin3" -i
            echo ""
          fi

          if  scanvirus_mswin4 != "" ]; then
            echo "$scanvirus_mswin4";
            clamscan -r "$scanvirus_mswin4" -i
            echo ""
          fi

          if  scanvirus_mswin5 != "" ]; then
            echo "$scanvirus_mswin5";
            clamscan -r "$scanvirus_mswin5"
          fi

          #read -p "Done. Press any key..." -n1 -s;echo ""

    elif  $1 == "-linux" ] ||  $1 == "-l" ]; then
            echo "Scanning linux..."  
            #which scans linux only. Both?
            #clamscan -r / --exclude-dir=/sys --exclude-dir=/proc --exclude-dir=/dev --cross-fs=no  
            #su -c "freshclam;clamscan -r / --exclude-dir=/sys --exclude-dir=/proc --exclude-dir=/dev --follow-dir-symlinks=0  --follow-file-symlinks=0 --log=scan.log"
            clamscan -r / --exclude-dir=/sys --exclude-dir=/proc --exclude-dir=/dev --follow-dir-symlinks=0  --follow-file-symlinks=0 -i
 
    elif  $1 == "-help" ] ||  $1 == "-h" ]; then
        echo ""
        echo "Scan Virus"
        echo "help commands"
        echo "-------------"
        echo "-linux or -l:  virus scan linux files"
        echo "-mswin or -w:  virus scan windows files"
        echo "--setup:  setup scanvirus"
        echo "--kdeicons:  setup icons"
        echo ""
            
    elif  $1 == "--setup" ]; then
        echo "ScanVirus Setup;
        su -c "zypper --non-interactive install clamav;chkconfig freshclam on;freshclam;exit"
            
    elif  $1 == "--kdeicons" ]; then
            Create_KDE_linux_scan_icon
            Create_KDE_windows_scan_icon   
            echo "KDE Icons Created"
            
    else
        echo ""
        echo "Scan Virus"
        echo "-------------------"
        echo "-h:  show help file"
        echo ""
    fi
exit 0 
# End Of Script


Yes, this e.g.:

    if  $1 == "-mswin" ] ||  $1 == "-w" ]; then

It should rather be:

    if  $1 = "-mswin" -o $1 = "-w" ]; then

(the ‘-o’ means “or”, see also "man ")
This also applies to the other similar lines of course.

And again, a ‘;’ is not needed at the end of a line. There still are some left… (but they don’t harm either)

That line gives a “error: too many parms”. The other works.

The script works as designed for the moment. thanks to all for the help and tips. Still need to test it more and take it to next stage.

Right, that happens when $1 is empty, i.e. you don’t pass any parameter to the script.

So put it into quotes to prevent an error:

if  "$1" = "-mswin" -o "$1" = "-w" ]; then

My complete script uses this style:

if  "$1" == "-mswin" ] ||  "$1" == "-w" ]; then

On the command line, this works with “scanvirus” or “sh scanvirus”. Also, this works under the shortcut icon. Is this a compatibility issue in Linux Bash?

No, not at all.
If you run your script, it is actually run in bash because of its first line (“shebang”, the #!/bin/bash).

I’m just not used to that notation, and it didn’t work here when I tried it. But I now know that this was because of the missing quotes, exactly the same reason why my line didn’t work for you… :wink:

So, you have to put the $1 into quotes. If it is undefined, it expands to nothing, so you’d get:

if  == "mswin" ]

or

if  = "mswin" ]

which is nonsense of course and bash complains about it.

If you put it in quotes, it will expand to this if empty:

if  "" == "mswin" ]

or

if  "" = "mswin" ]

which is perfectly valid.
(I omitted things there of course… :wink: )

Also, the parameter might contain spaces, which would also cause an error if you don’t put that $1 into quotes. Although that’s not really an issue in your case.

If $1 happens to be operator (like -f) it will be misinterpreted. Which is why it is common to use

x"$1" = x"-mswin"

to “quote” initial dash.

Are you sure? How exactly will it be misinterpreted?

It seems to work fine here: (using $x for obvious reasons)

wolfi@amiga:~> x=-mswin
wolfi@amiga:~> if  "$x" = "-mswin" -o "$x" = "-w" ]; then echo "yes"; fi
yes
wolfi@amiga:~> x=xxx
wolfi@amiga:~> if  "$x" = "-mswin" -o "$x" = "-w" ]; then echo "yes"; fi
wolfi@amiga:~> x=-w
wolfi@amiga:~> if  "$x" = "-mswin" -o "$x" = "-w" ]; then echo "yes"; fi
yes
wolfi@amiga:~> x=-f
wolfi@amiga:~> if  "$x" = "-mswin" -o "$x" = "-w" ]; then echo "yes"; fi
wolfi@amiga:~> if  "$x" = "-mswin" -o "$x" = "-f" ]; then echo "yes"; fi
yes

Thanks for the info on quoting. Also, I was using single quotes and that didn’t work.

I meant this for compatibility with two examples given.

if  "$1" == "-mswin" ] ||  "$1" == "-w" ]; then

if  "$1" = "-mswin" -o $1 = "-w" ]; then

The first line is more readable than the second. Is this the format for bash?

FYI, i’m taking the script up another level to read a file of path names.

Hi,

The x"$1" trick AFAIK is only needed if you want your code to be portable in any Unix shell known to men :). It works even on the *csh shell which is not even a descendant of the Ancient Bourne shell. Also the leading (-) dash option should work on any POSIX compliant shell.

Actually no more. Apparently at least GNU test is smart enough to interpret its input according to number of arguments it gets. Sorry for confusion.

Yes, single quotes actually prevent the expansion of shell variables completely. I.e. ‘$1’ means “take $1 literally”, and delivers $1, not the content of $1.

The first line is more readable than the second. Is this the format for bash?

I’m not sure whether this is exclusive to bash.
But I do think that in the first case the ‘||’ is interpreted by the shell, whereas in the second case the whole condition (“$1” = “-mswin” -o $1 = “-w”) is evaluated by the ‘’ command (which is a normal executable in /usr/bin/, but also builtin to bash).
That would explain why only the second variant is mentioned in 's man page.

bash does support operators like “||” and “&&”, “a || b” means run command b if command a returns false, and “a && b” means run command b if a is true (and “a ; b” means run command b unconditionally after a).
So in the first case you actually “run” the ‘’ command twice, if the first condition is false.
The second variant is probably more portable as it doesn’t depend on shell features (but then, the question would still be whether the syntax for if/then/else is the same in the shell you would be using I suppose).

Btw, is only a synonym for “test”, so something like this would also work:

if test "$1" = "-w"; then

May my remark will add to the confusion (thus you may happily ignore it), but I prefer to use the, internal to bash,

 ....... ]]

construct above using the

  

or

test

command.

No comment about your preference. That’s perfectly fine with me.

But I just want to stress again that also ‘’ and ‘test’ are internal to bash, although they do exist in /usr/bin/ as well.
Your post might suggest they are not and have to be loaded from disk.

There is a difference though between ‘’ (‘test’) and ‘’:

   When used with `', the `<' and `&gt;' operators sort
lexicographically using the current locale.  The `test' command uses
ASCII ordering.

(from bash’s info page)
Not really relevant for the script at hand, but still worth mentioning I think.

Another thing I just spotted in that info page:
“=” should be used for POSIX compliance, but bash accepts both “=” and “==” to compare strings. Both do the same.

You are correct, but the fact that [/test are also internal to bash was already mentioned by you earlier, thus I assumed that that as known by the careful reader. :wink:

And of course there is a difference, else my preference would be futile.

My preference derives from using ksh. My experience is that it is easier to use the [[ … ]] because the definition what you put between the and ]] is is easier to understand. At least for me.

Hi,

Any POSIX compliant shell should comply/follow this rule.

http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html

The shell (POSIX compliant) does not use external commands/executable if there is an internal/builtin available. That is true even in the cli or in a script.

See

PAGER='less +/^COMMAND\ EXECUTION' man bash

If you want to see which will get executed first run:

type -a command

i.e.

type -a ''
type -a test

The output is exactly the order of on which bash will search do/execute the commands, of course you can always use the absolute path or use the internal command

command

see

help command

Also one can use the ** in front of the command as an alternative.

grep will run the alias/function which is defined by openSUSE.

while** \grep **will search for the PATH directly.

grep multiversion /etc/zypp/zypp.conf

The grep above will print red colors for the match because of the alias which is found in

type -a grep

While

command grep multiversion /etc/zypp/zypp.conf

or

\grep multiversion /etc/zypp/zypp.conf

or

/usr/bin/grep multiversion /etc/zypp/zypp.conf

or

Will not print any colors.

Hi,

see also

help test

because test is a builtin, and in builtins/internal commands one should use help.

Also

PAGER='less +/^CONDITIONAL\ EXPRESSIONS' man bash