50

I would like to check if a certain file exists on the remote host. I tried this:

$ if [ ssh user@localhost -p 19999 -e /home/user/Dropbox/path/Research_and_Development/Puffer_and_Traps/Repeaters_Network/UBC_LOGS/log1349544129.tar.bz2 ] then echo "okidoke"; else "not okay!" fi
-sh: syntax error: unexpected "else" (expecting "then") 
stdcerr
  • 13,725
  • 25
  • 71
  • 128

13 Answers13

63

In addition to the answers above, there's the shorthand way to do it:

ssh -q $HOST [[ -f $FILE_PATH ]] && echo "File exists" || echo "File does not exist";

-q is quiet mode, it will suppress warnings and messages.

As @Mat mentioned, one advantage of testing like this is that you can easily swap out the -f for any test operator you like: -nt, -d, -s etc...

Test Operators: http://tldp.org/LDP/abs/html/fto.html

JP Lew
  • 4,121
  • 2
  • 32
  • 45
  • 6
    +1, but this assumes the receiving host has bash and that it's the default shell of the user. – kojiro Aug 17 '13 at 17:59
  • 4
    I really really like your solution. And just for some freshmen like me if-else version: if ssh -q ${HOST} [[ -f ${FILE_PATH} ]] ; then echo "File exists" ; else "File not found" ; fi – yatsek May 15 '14 at 08:36
  • This is super old, but I need help. This works perfectly, but I'm iterating in several files, my need is to stop when I found the first one. How can I do that? – X3MBoy Oct 30 '18 at 14:42
  • How could this be put as an `if` statement? – Yanick Rochon Nov 17 '22 at 15:04
  • 2
    Double brackets around the -f test are unnecessary - single brackets work just fine here. In 2023, most people will be encountering bash or ksh which supports double-bracket syntax but older sh does not. – raindog308 Mar 15 '23 at 23:23
59

Here is a simple approach:

#!/bin/bash
USE_IP='-o StrictHostKeyChecking=no username@192.168.1.2'

FILE_NAME=/home/user/file.txt

SSH_PASS='sshpass -p password-for-remote-machine'

if $SSH_PASS ssh $USE_IP stat $FILE_NAME \> /dev/null 2\>\&1
            then
                    echo "File exists"
            else
                    echo "File does not exist"

fi

You need to install sshpass on your machine to work it.

Elshan
  • 7,339
  • 4
  • 71
  • 106
Florin Stingaciu
  • 8,085
  • 2
  • 24
  • 45
  • How to invert the if? `if [ -n ... ]`? – redolent Feb 27 '13 at 20:20
  • 15
    This would be better if you just used `test` instead of `stat`. `test` is an IEEE standard. `stat` is nonstandard. `test` won't output messages on failure, it just returns a standard exit status. – kojiro Aug 17 '13 at 17:53
  • It works but asks for login and password of `$HOST`. Is it possible to have password less authentication or is there a way to enter login and password in the script itself. Thanks – Yash Nov 28 '18 at 11:19
  • @Yash Before running this script you'll have to generate the ssh public/private key pair on your local machine first, `yes 'y' | ssh-keygen -t rsa -f ~/.ssh/replace_me_with_a_keyname -N " "` then scp over the public key to the remote machine and add your local machine to known_hosts. `scp -o StrictHostKeyChecking=no ~/.ssh/replace_me_with_a_keyname.pub host_username@host_ip:~/.ssh/`. On first run it will require username and password, but everytime you ssh to run more scripts, it will automatically log you in with the key authentication – wski Nov 28 '18 at 18:53
  • Did this get tested with a banner ? – mckenzm Jun 09 '19 at 23:22
49

Can't get much simpler than this :)

ssh host "test -e /path/to/file"
if [ $? -eq 0 ]; then
    # your file exists
fi

As suggested by dimo414, this can be collapsed to:

if ssh host "test -e /path/to/file"; then
    # your file exists
fi
karni
  • 894
  • 8
  • 15
  • 6
    Well yes it can, you could swap out `[ $? -eq 0 ]` with the `ssh` command itself :) – dimo414 Jun 26 '15 at 22:26
  • @dimo414 Could you be more specific about your suggestion? – Dr_Zaszuś Jan 13 '20 at 13:16
  • @Dr_Zaszuś `foo; if (( $? == 0 )); then ...; fi` is equivalent to `if foo; then ...; fi`. It's rarely necessary to use `$?` simply to check if a command succeed. Here's [another answer](https://stackoverflow.com/a/31348007/113632) where I talk about this. – dimo414 Jan 14 '20 at 18:34
  • You can also remove the double quotes in this case. – pmiguelpinto90 Jul 29 '21 at 14:16
13

one line, proper quoting

ssh remote_host test -f "/path/to/file" && echo found || echo not found
estani
  • 24,254
  • 2
  • 93
  • 76
8

You're missing ;s. The general syntax if you put it all in one line would be:

if thing ; then ... ; else ... ; fi

The thing can be pretty much anything that returns an exit code. The then branch is taken if that thing returns 0, the else branch otherwise.

[ isn't syntax, it's the test program (check out ls /bin/[, it actually exists, man test for the docs – although can also have a built-in version with different/additional features.) which is used to test various common conditions on files and variables. (Note that [[ on the other hand is syntax and is handled by your shell, if it supports it).

For your case, you don't want to use test directly, you want to test something on the remote host. So try something like:

if ssh user@host test -e "$file" ; then ... ; else ... ; fi
Mat
  • 202,337
  • 40
  • 393
  • 406
5

Test if a file exists:

HOST="example.com"
FILE="/path/to/file"

if ssh $HOST "test -e $FILE"; then
    echo "File exists."
else
    echo "File does not exist."
fi

And the opposite, test if a file does not exist:

HOST="example.com"
FILE="/path/to/file"

if ! ssh $HOST "test -e $FILE"; then
    echo "File does not exist."
else
    echo "File exists."
fi
rouble
  • 16,364
  • 16
  • 107
  • 102
3
ssh -q $HOST [[ -f $FILE_PATH ]] && echo "File exists"

The above will run the echo command on the machine you're running the ssh command from. To get the remote server to run the command:

ssh -q $HOST "[[ ! -f $FILE_PATH ]] && touch $FILE_PATH"
Michael0x2a
  • 58,192
  • 30
  • 175
  • 224
None
  • 41
  • 1
3

Silent check if file exist and perform if not

if ! ssh $USER@$HOST "test -e file.txt" 2> /dev/null; then
  echo "File not exist"
fi
Aidar Gatin
  • 755
  • 1
  • 7
  • 9
1

You can specify the shell to be used by the remote host locally.

echo 'echo "Bash version: ${BASH_VERSION}"' | ssh -q localhost bash

And be careful to (single-)quote the variables you wish to be expanded by the remote host; otherwise variable expansion will be done by your local shell!

# example for local / remote variable expansion
{
echo "[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'" | 
    ssh -q localhost bash
echo '[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"' | 
    ssh -q localhost bash
}

So, to check if a certain file exists on the remote host you can do the following:

host='localhost'  # localhost as test case
file='~/.bash_history'
if `echo 'test -f '"${file}"' && exit 0 || exit 1' | ssh -q "${host}" sh`; then
#if `echo '[[ -f '"${file}"' ]] && exit 0 || exit 1' | ssh -q "${host}" bash`; then
   echo exists
else
   echo does not exist
fi
tarok
  • 11
  • 1
0

I wanted also to check if a remote file exist but with RSH. I have tried the previous solutions but they didn't work with RSH.

Finally, I did I short function which works fine:

function existRemoteFile ()
{
REMOTE=$1
FILE=$2
RESULT=$(rsh -l user $REMOTE  "test -e $FILE && echo \"0\" || echo \"1\"")
if [ $RESULT -eq 0 ]
then
    return 0
else
    return 1
fi
}
miguialberto
  • 316
  • 1
  • 3
  • 14
0

On CentOS machine, the oneliner bash that worked for me was:

if ssh <servername> "stat <filename> > /dev/null 2>&1"; then echo "file exists"; else echo "file doesnt exits"; fi

It needed I/O redirection (as the top answer) as well as quotes around the command to be run on remote.

Abhimanu Kumar
  • 1,751
  • 18
  • 20
-1

This also works :

if ssh user@ip "[ -s /path/file_name ]" ;then 
  status=RECEIVED ; 
 else 
  status=MISSING ; 
 fi
DollyShukla
  • 107
  • 5
-1
#its simple

if [[ "`ssh -q user@hostname ls /dir/filename.abc 2>dev/null`" == "/dir/filename.abc" ]]
then
    echo "file exists"
else
    echo "file not exists"
fi
weirdan
  • 2,499
  • 23
  • 27
  • 1
    It's never a good idea to rely on the output of `ls` for scripted logic. It can change depending on your account configuration and other considerations. – joanis Mar 31 '21 at 19:13