Is it possible to do this:

ssh user@socket command /path/to/file/on/local/machine

That is to say, I want to execute a remote command using a local file in one step, without first using scp to copy the file.

  • It's possible if the remote computer has a network mount of a parent directory of the file of the local machine or if you redirect the file into the ssh command – h3rrmiller Oct 26 '12 at 17:24

You missed just one symbol =)

ssh user@socket command < /path/to/file/on/local/machine
  • Of course! I wonder why I didn't consider input redirection over ssh?! – jsj Oct 26 '12 at 13:08
  • What if remote command can only take a file argument and not read from stdin? – iruvar Oct 26 '12 at 14:48
  • @ChandraRavoori in that case you need to copy it with scp before. – rush Oct 26 '12 at 15:53
  • 4
    @ChandraRavoori You can try giving it the file argument /dev/stdin or -. May or may not work (/dev/stdin is a file, but seeking it will fail) – derobert Oct 26 '12 at 16:03
  • 1
    @derobert and rush, played around with it a bit and discovered a hacky way to do it using process substitution under bash. This is still subject to the seeking limitation and can get unwieldy with all the additional quoting that will be needed. Example follows. cat test.file | ssh user@machine 'bash -c "wc -l <(cat -)"' – iruvar Oct 26 '12 at 19:04

One way that works regardless of the command is to make the file available on the remote machine via a remote filesystem. Since you have an SSH connection:

  1. Establish a reverse SSH tunnel. See also SSH easily copy file to local system
  2. Mount a directory tree of your machine containing the file to share on the remote machine with SSHFS. (Example)
  • Anyway this way requires additional movements before command execution. – rush Oct 27 '12 at 6:09
  • @Gilles: I think the original title was misleading, and you understood his question based on the misleading title. As far as I can tell, thought, he didn't actually want to act on the local file, but just pass it in as input. (But your answer is amazing, if I understand it correctly! Maybe I should ask the question you answered, just to give you a place to put the answer where you'll get proper credit for it.) I've edited the questions title to make it consistent with the body and with the chosen answer. – iconoclast Aug 1 '14 at 16:10
  • @iconoclast I don't remember my state of mind when I wrote this, but I go by this answer. It requires some setup but has the advantage of generalizing beyond the immediate requirement to other cases where it isn't enough to copy the input. I'd also have mentioned redirection if someone else hadn't done it. The more general question has been asked many times in slightly different forms. – Gilles Aug 1 '14 at 17:02
  • Okay, I must have misunderstood your answer. I didn't try it, but inferred that since you were establishing a reverse tunnel (from remote to local host?) you were allowing the local file to be modified by the remote machine. Is that not the case? – iconoclast Aug 1 '14 at 17:21
  • @iconoclast Yes, this allows the remote machine to modify the local file (in addition to allowing it to read it, which is what the question requires). – Gilles Aug 1 '14 at 17:22
# What if remote command can only take a file argument and not read from stdin? (1_CR)
ssh user@socket command < /path/to/file/on/local/machine
cat test.file | ssh user@machine 'bash -c "wc -l <(cat -)"'  # 1_CR

As an alternative to bash process substitution <(cat -) or < <(xargs -0 -n 1000 cat) (see below) you can just use xargs and cat to pipe the contents of the specified files to wc -l (which is more portable).

# Assuming that test.file contains file paths each delimited by an ASCII NUL character \0
# and that we are to count all those lines in all those files (provided by test.file).

#find . -type f -print0 > test.file
# test with repeated line count of ~/.bash_history file
for n in {1..1000}; do printf '%s\000' "${HOME}/.bash_history"; done > test.file

# xargs & cat
ssh localhost 'export LC_ALL=C; xargs -0 -n 1000 cat | wc -l' <test.file

# Bash process substitution
cat test.file | ssh localhost 'bash -c "export LC_ALL=C; wc -l < <(xargs -0 -n 1000 cat)"'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.