How to treat variable in bash?

Asked

Viewed 157 times

2

I’m having a problem, I’m making a bash script to run using crontab, which synchronizes my SSD files, with the hard drive and Dropbox.

Script:

#!/bin/bash -

PC_DIR="~/Programming"
DROP_DIR="~/Dropbox/Programação"

PC_FILES="$(find ${PC_DIR} -follow)"
DROP_FILES="$(find ${DROP_DIR} -follow)"

for FILE1 in "${PC_FILES}"
do
    echo "FILE1=${FILE1}"
    for FILES2 in "${DROP_FILES}"
    do
        echo "FILE2=${FILE2}"
        if [ "${FILE1}" -nt "${FILE2}" ];
        then
            cp "${FILE1}" "${FILE2}"

        elif [ "${FILE1}" -ot ""${FILE2} ];
        then
            cp "${FILE2}" "${FILE1}"
        fi
    done
done

The problem with the script is that it treats the "Filex" variables as a large block of text with several line breaking functions (' n') ex:

FILE1=~/Programming
~/Programming/C++
~/Programming/C++/teste.cpp
~/Programming/C++/test.cpp

Pórem, to do the tests of 'Newerthan' and 'Olderthan', I need to be able to look at each line as a different directory, and not as a big block, how can I do this?

  • Gabriel, watch the remote rsync inside the machine or remote plant. Example: rsync -l -turv dir/ maquina.remota:dir/

  • Gabriel, it seems to me that your algorithm copies the newest file onto everyone else...

1 answer

1


The mistake is in "${PC_FILES}" and "${DROP_FILES}". With the quotes, you’re basically telling the algorithm to capture everything as a string and play in the variable FILE1 and FILE2 respectively.

The solution to your code is to do it this way:

#!/bin/bash

PC_DIR="after"
DROP_DIR="bkp"

PC_FILES="$(find ${PC_DIR} -follow)"
DROP_FILES="$(find ${DROP_DIR} -follow)"

IFS=$'\n'

for FILE1 in ${PC_FILES}
do
    echo "FILE1=${FILE1}"
    for FILE2 in ${DROP_FILES}
    do
        echo "FILE2=${FILE2}"
        if [ "${FILE1}" -nt "${FILE2}" ];
        then
           echo "Copia ${FILE1} para ${FILE2}"

        elif [ "${FILE1}" -ot ""${FILE2} ];
        then
            echo "Copia ${FILE2} para ${FILE1}"
        fi
    done
done

There is another way, too, to read find output (or any other command) which is to use the command read together with the command while

#!/bin/bash -

PC_DIR="after"
DROP_DIR="bkp"

PC_FILES="$(find ${PC_DIR} -follow)"
DROP_FILES="$(find ${DROP_DIR} -follow)"

IFS="\\"

while read FILE1; do

        while read FILE2; do

                if [ "${FILE1}" -nt "${FILE2}" ]; then
                    echo -e "Copia ${FILE1} para ${FILE2}\n"

                elif [ "${FILE1}" -ot ""${FILE2} ]; then
                    echo -e "Copia ${FILE2} para ${FILE1}\n"
                fi

        done <<< ${DROP_FILES}

done <<< ${PC_FILES}

I’d rather leave the while¹

Note that add one more line, the IFS. This variable is nothing more than a "separator". It basically tells bash how to recognize fields, boundaries, etc.

¹ To know the difference between while/for, I recommend reading Reading Lines from a file with bash: for vs. while

  • the answer pointed out and fixed the asked problem (+1) but I warn that the algorithm is a bit strange... (copies the most recent file over all others)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.