Search code examples
bashshellvariablesrsync

bash "command not found" error even though the command fires


I'm building some small test files to start learning bash scripting.

One of the files I built performs an rsync command. The command fires successfully, but the line in the script that causes the command to fire throws the error line 15: =building: command not found when the script is fired in the terminal.

Here's the script:

#!/bin/bash

clear

cd ~/Desktop

mkdir -p ./GGERPTTESTINGSANDBOX/source_folder/
mkdir -p ./GGERPTTESTINGSANDBOX/target_folder/

touch ./GGERPTTESTINGSANDBOX/source_folder/file1.txt
touch ./GGERPTTESTINGSANDBOX/source_folder/file2.txt
touch ./GGERPTTESTINGSANDBOX/source_folder/file3.txt

statement="/usr/bin/rsync -avzh --progress ./GGERPTTESTINGSANDBOX/source_folder/ ./GGERPTTESTINGSANDBOX/target_folder/"
$statementResult=$($statement) # the error points to this line. 

As I said above, when I run this script the rsync works fine. I've pulled the command out and fired it directly in the terminal and it works fine.

At first I did not have the full path to the rsync command in the script so I added it thinking that pulling the command from my path variable may be the issue but it's still throwing the error.

I've also tried putting the statement directly into the $() characters rather than passing it in via variable and the error still happens.

Any ideas of what I'm missing?


Solution

  • Get rid of the leading dollar sign.

    statementResult=$($statement)
    

    I also encourage you to store commands in functions rather than in variables.

    statement() {
        rsync -avzh --progress ./GGERPTTESTINGSANDBOX/source_folder/ ./GGERPTTESTINGSANDBOX/target_folder/
    }
    
    statementResult=$(statement)
    

    Functions can take parameters, making it easy to invoke a pre-defined command with different arguments. When their parameters are properly quoted they can handle file names with spaces and other unusual--but permitted--characters.

    For example, you could parameterize your function so it just does the rsync and leaves the path names up to the caller:

    synchronize() {
        local dir=$1
        local src=$2
        local dest=$3
    
        rsync -avzh --progress "$dir/$src/" "$dir/$dest/"
    }
    
    result=$(synchronize ./GGERPTTESTINGSANDBOX source_folder target_folder)
    result=$(synchronize ./GGERPTTESTINGSANDBOX 'from here' 'to here')
    

    Notice how this accepts directory names with spaces (from here and to here). That would be very difficult to do with a variable holding the same code.