varible being erased with no cause

This is part of my scanvirus script. I need to expand the logging. The code around is complex, but just look at the small additions.

I’m baffled as why this this variable is clearedl. This is a short clear var, apend var, and print var. It’s very simple, yet won’t work! ARG! There is no logic to this varible being cleared. Need help

#partition_scan ostype moveflag partition1 partition2 partitionx
        Partition_Log=''; mod start var null

        #delete first two parms
        shift 2
        Current_Vault_Folder="$Virus_Vault_Folder/$OStype "
        Current_Vault_Folder+=$(date +'%m-%d-%Y %I:%M:%S%P')
        mkdir "${Current_Vault_Folder}"
        printf "
.....scanvirus %s.....
" $OStype | tee "$Current_Vault_Folder/scanresults.log"
        blkid | sed 's/: /:/g' | sed 's/\" /:/g' | while read -ra line

            for blkid_field in ${line
[li]}[/li]            do
                if  [[ "$blkid_field" == "TYPE="* ]];then
                    #cut 'type='
                elif  [[ "$blkid_field" == *"LABEL="* ]];then
                    #cut 'label='
            #cut /dev/
            Temp_MP=${Device_Label#/*/}    #printf "Temp_MP= %s
" ${Temp_MP}

            #                                                               cut devicename
            Mount_Point=$( lsblk -l -o name,mountpoint | grep "${Temp_MP}" | sed "s/${Temp_MP} //g" )

            #cut leading spaces
            Mount_Point=${Mount_Point#   }

            #printf "
            #printf "Device_Label= '%s'
" $Device_Label
            #printf "File_System = '%s'
" $File_System
            #printf "Drive_Label = '%s'
" $Drive_Label
            #printf "Mount_Point = '%s'
" $Mount_Point

            #scan for matching partition types in parms
            for parm;
                #printf "FS= %s:parm= %s  " $File_System $parm
                #if [ "$File_System" = "$parm" ];then
                #    printf "true
                #    printf "false

                if [ "$File_System" = "$parm" ];then

            #if file system match
            if [ "$Found_Match" = 'true' ]; then
                #if [ "$Drive_Label" = "System Reserved" ]; then
                    #printf "Skipping System Reserved...

                Partition_log+="$Drive_Label"; mod append to string
                printf "Partition_log=%s
" $Partition_log; mod string apend added successfully
                printf "__________________________________________________
" | tee -a "${Current_Vault_Folder}/scanresults.log"

                #if device not mounted
                if [ "$Mount_Point" = '' ]; then

                    command_output_scandir=$(udisksctl mount -b "$Device_Label");mount_error=$?
                    printf "%s
" $command_output_scandir
                    #cut out scan directory
                    command_output_scandir=${command_output_scandir#Mounted\ *\ at\ }
                    #printf "%s
" $Mount_Point
                    if [ "$mount_error" != 0 ]; then
                        printf "Error: mount %s
" $Drive_Label

                printf "
scanning: %s %s
" $Drive_Label $Mount_Point | tee -a "${Current_Vault_Folder}/scanresults.log"

                # trap keyboard interrupt (control-c)
                trap "control_c $Device_Mounted_Flag $Device_Label" exit
                #scan mswin and linux differently
                if [ "$OStype" = 'linux' ]; then
                    clamscan -r "$Mount_Point" --exclude-dir=/sys --exclude-dir=/proc --exclude-dir=/dev --exclude-dir=/.snapshots --follow-dir-symlinks=0 --follow-file-symlinks=0 --cross-fs=no | Scan_Results_Filter
                elif [ "$OStype" = 'mswin' ]; then
                    #scan only or move files
                    if [ "$Move_Flag" = 'true' ]; then
                        printf "Move to Virus Vault: /var/log/VirusVault/
                        clamscan -r "$Mount_Point" "--move=${Current_Vault_Folder}" --follow-dir-symlinks=0 --follow-file-symlinks=0 --cross-fs=no | Scan_Results_Filter
                        printf "Scan only
                        clamscan "$Mount_Point" --follow-dir-symlinks=0 --follow-file-symlinks=0 --cross-fs=no | Scan_Results_Filter
                    #printf "movefile_parm= %s
" $Movefile_Parm

                #if drive mounted, unmount it
                if [ "$Device_Mounted_Flag" = 'true' ];then
                    #flush buffers to make sure all the data is written to drive
                    sync -f "$Device_Label"

                    command_output_unmount=$(udisksctl unmount -b "$Device_Label");unmount_error=$?
                    printf "%s
" ${command_output_unmount%.}    
                printf "__________________________________________________
" | tee -a "${Current_Vault_Folder}/scanresults.log"

            #printf "next loop
            if [ "$scanvirus_trap_flag" = 'true' ]; then

        printf "Partition_log=%s
" $Partition_log;  mod print string   string is null, but it's not being cleared by any code.

        #virus vault files read only
        #chmod 744 "${Current_Vault_Folder}"

Congratulations! You have found one of the most-annoying things I’ve
found with regard to variables and loops that have data piped into them.

I first found this when trying to read a file using:

cat $file | while read oneline; do ... done

I liked this form because it was clear, from the top of the loop, what was
being read.

I had to change my code to just use a redirect to read the file, and then
the problem was solved, or so I remember it, but that requires having the
redirect in at the end of the loop, so it seemed less-obvious to me, but
the variables within the loop then maintained their values. Frustrating,
I know, but it’s the way the system works, and it is (as I recall) because
you are invoking a sub-shell when you do it your/my-original way, and that
sub-shell dies when the loop ends, so all variables within also die. Stop it.

Having found this issue, you are now an expert script person. Congrats!

Good luck.

If you find this post helpful and are logged into the web interface,
show your appreciation and click on the star below.

If you want to send me a private message, please let me know in the
forum as I do not use the web interface often.

Can you show the line(s) where the problem is? This app is a beast to understand and I wrote it. :stuck_out_tongue:

Well, yes; I am sorry I was not clear the first time.

Your variable is only within one loop, and that is the only while loop,
and the line starting it looks like this:

blkid | sed 's/: /:/g' | sed 's/\" /:/g' | while read -ra line

Since you are piping data from a command, instead try to read it in from a
file, which probably means write this command’s output to a file and then
redirect it in:

blkid | sed 's/: /:/g' | sed 's/\" /:/g' > "${TMPFILE}";
while read -ra line; do
#Stuff goes here
done < "${TMPFILE}
rm "${TMPFILE}";

Let us know how it goes.

Good luck.

If you find this post helpful and are logged into the web interface,
show your appreciation and click on the star below.

If you want to send me a private message, please let me know in the
forum as I do not use the web interface often.

More details.


With a bit a tweaking, the new log works. Add what drives what you have scanned in an mswin scan.

However, I found it seemed to cause a bug or found one in the trap system. It also uncovered a bug in the drive search for mswin partition. For some reason, it’s adding a quote into the drive label. NTFS → NFTS". Both bugs will take time to fix.

Sometimes, I just want to hit this computer with a sledgehammer! :stuck_out_tongue:

Thanks for the help.

This topic piqued my interest.

So, some more possibilities although I consider ab’s reference excellent…

This topic is described similarly but in different words in the TLDP’s page on subshells

Both the Parent/Child subshell variable issue and LOOPs are described in the TLDP’s “Gotcha” Bash scripting page with some additional suggestions

The following first answer recommends the “Command Grouping” method

But, the second answer in the above link is most natural to me, because it’s the approach of most of today’s OOP… Defining individual functions. You should have no problem passing the result of a function to something else, even updating a global variable. Also, this type of structure should solve your problem of “beastly” code, making your code easy to read and easy to understand even with limited comments.

Interesting stuff…