1

I have the following script

ssh user@host << EOF

    STATUS="$(git status)"
    SEARCH_STATUS="Not a git"

    if [[ "$STATUS" == *$SEARCH_STATUS* ]]; then
        echo "Not a git repository"
    fi

EOF

I am getting the following error

-bash: line 3: file: No such file or directory

Which corresponds to this line

STATUS="$(git status)"

The issue here is, is that the above line is working, git does exist, and is executing as planned, and storing the output of the git command in STATUS, and the If statement is executing as planned as well, which echo's when the status of git matches the "Not a git" string...

what I don't understand is, is why it's throwing that error, any ideas?

Kusalananda
  • 333,661
  • This isn't a duplicate of the questions you marked it a duplicate of... I am not asking, how to pass and set variables, or how to force a remote command, I am asking, why am I getting No such file or directory on a specific line – Jeffrey L. Roberts Aug 09 '18 at 10:43
  • The cause is the same. The contents of the here-document is evaluated locally. The solution is the same. Quote the here-document (or the parts of it that shouldn't be evaluated). – Kusalananda Aug 09 '18 at 11:30

1 Answers1

1

The shell is expanding the commands on your machine not the remote one.

Quote 'EOF'

ssh user@host<<'EOF'
STATUS="$(git status)"
EOF

From man bash:

Here Documents

This type of redirection instructs the shell to read input from the current source until a line containing only delimiter (with no trailing blanks) is seen. All of the lines read up to that point are then used as the standard input for a command.

The format of here-documents is:

      <<[-]word
              here-document
      delimiter

No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter case, the character sequence \ is ignored, and \ must be used to quote the characters \, $, and `.

Edit

Your test is also wrong. You could use grep to check if the required string is in the output:

ssh user@host <<'EOF'
if git status 2>&1 | grep -q 'Not a git' ; then
  echo 'Not a git repository'
fi
EOF

or if you want to retain the status in a variable

ssh user@host <<'EOF'
STATUS=$(git status 2>&1)
if echo $STATUS | grep -q 'Not a git' ; then
  echo 'Not a git repository'
fi
EOF

Note that you will have to redirect STDERR to STDOUT with 2>&1

Edit 2

If you force bash you can also

ssh user@host bash <<'EOF'
STATUS=$(git status 2>&1)
SEARCH_STATUS="ot a git"
echo "STATUS=$STATUS"
if [[ "$STATUS" == *$SEARCH_STATUS* ]]; then
  echo 'Not a git repository'
fi
EOF

Beware that on macOS and Linux I got different capitalisations of 'Not'/'not'. Therefore the SEARCH_STATUS is just ot a git and not Not a git

Matteo
  • 9,796
  • 4
  • 51
  • 66
  • I quoted EOF, however, now the script does not work as planned... it does not echo "Not a git repository" ... – Jeffrey L. Roberts Aug 09 '18 at 10:44
  • There are also problems with your test * is expanded by the shell with the list of files in the current directory. It cannot be used for string comparisons. – Matteo Aug 09 '18 at 11:28
  • 1
    @Matteo Actually, in Bash, the * within [[ ... ]] is not used for filename expansion but for pattern matching. Try [[ foo == f* ]] && echo true, it prints true. OTOH, * within [ ... ] does trigger filename expansion because [ is a command (usually built in the shell), not a reserved word like [[ and ]]. – nxnev Aug 09 '18 at 11:48
  • @nxnev You are right I didn't notice the [[, but there is no guarantee that bash will be the shell used on the other side – Matteo Aug 09 '18 at 11:49
  • @Matteo Yeah, fair point. – nxnev Aug 09 '18 at 11:52