Alex Forsyth
Alex Forsyth

Reputation: 187

Bash command substitution executing before earlier code

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?

Upvotes: 0

Views: 85

Answers (1)

chepner
chepner

Reputation: 531345

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'"

Upvotes: 2

Related Questions