0
ssh -i "path/to/my/key.key" ip.ip.ip.ip "mkdir a/a; sql 'query;' > a/a/file.txt; if [ -f a/a/file.txt ]; then if [ $(wc -l a/a/file.txt) -ge 2 ]; then echo 'done'; fi; fi; exit"

After connecting via ssh, I'm basically making a directory, writing a sql query to a file. If that file exists, then I check if its word count is greater than 1. If word count greater than 1, I echo done, then exit.

However, I get this error:

wc: a/a/file.txt open: No such file or directory

It seems as if the command substitution $(wc -l a/a/file.txt) is executing first (at least before the sql query), so the file hasn't been created yet. Is there some way to force this to execute in the order its written, or is there some better way to do this?

3
  • 5
    Yes, you have the string in double quotes so variables/command substitutions/etc. all happen on the calling side. You need single quotes or to escape the expansions to avoid that. Commented Jul 1, 2015 at 16:26
  • 5
    Also the output from wc -l file isn't directly usable in a -gt test it has the filename in it. Use wc -l <file to avoid that. Commented Jul 1, 2015 at 16:27
  • The -f test is not necessary; once sql returns, that file is guaranteed to exist because the shell creates it before it executes sql. Commented Jul 1, 2015 at 17:12

1 Answer 1

2

You need to protect the command substitution from being expanded before ssh is called; you can wrap the entire command in single quotes, or simply escape the $ within the double quotes (shown here). (Newlines inserted for clarity; they aren't necessary, but can be used if you want.)

ssh -i "path/to/my/key.key" ip.ip.ip.ip "mkdir -p a/a
 sql 'query;' > a/a/file.txt
 [[ \$(wc -l < a/a/file.txt) -ge 2 ]] && echo 'done'"

The -f test is unnecessary; the shell creates the file before running sql, and the file will exist whether or not the command produces any output. The exit is unnecessary as well; the shell will exit as soon as the last command is executed anyway.

One (hacky?) way to avoid the command substitution altogether is to simply try to read 2 lines from the file with read:

ssh ... "mkdir -p a/a
 sql 'query;' > a/a/file.txt
 { read && read; } < a/a/file.txt && echo 'done'"
Sign up to request clarification or add additional context in comments.

2 Comments

I'm dealing with a buggy version of sql which is why I have to do these checks in the first place. The query seems to have 3 types of errors. 2 types write a one line error message to the file, which is why I check if it's at least two lines. The third type exits without writing to file, which is why I check if the file exists.
If the file doesn't exist at all, that's not due to sql; the shell creates the target of a redirection before the associated command is ever run. The one-line error message does require the line count; I'll amend my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.