18

Using JSch, is there a way to tell if a remote file exists without doing an ls and looping through the files to find a name match?

Thanks

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
cagcowboy
  • 30,012
  • 11
  • 69
  • 93

6 Answers6

20

You can also do something like this:

try {
    channelSftp.lstat(name);
} catch (SftpException e){
    if(e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE){
    // file doesn't exist
    } else {
    // something else went wrong
        throw e;
    }
}

If you do an lstat on something that doesn't exist you get an SftpExecption with an id of 2, otherwise you get information about the file.

Koubi
  • 33
  • 6
zelinka
  • 3,271
  • 6
  • 29
  • 42
  • if(e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) --> Where is the id came from? – ChocoMartin Nov 26 '21 at 04:04
  • I tried to use cd command with channelSftp and then check the file name. it did not work. concatenating the path and name did work. Thanks – sachyy Feb 23 '22 at 07:48
18

This is how I check directory existence in JSch.

Note: not related to this question, but some may find it useful.

Create directory if dir does not exist

ChannelSftp channelSftp = (ChannelSftp)channel;
String currentDirectory=channelSftp.pwd();
String dir="abc";
SftpATTRS attrs=null;
try {
    attrs = channelSftp.stat(currentDirectory+"/"+dir);
} catch (Exception e) {
    System.out.println(currentDirectory+"/"+dir+" not found");
}

if (attrs != null) {
    System.out.println("Directory exists IsDir="+attrs.isDir());
} else {
    System.out.println("Creating dir "+dir);
    channelSftp.mkdir(dir);
}
AabinGunz
  • 12,109
  • 54
  • 146
  • 218
  • 1
    This is the right solution, because it finds files with '*' in name → no globbing! – Nils-o-mat Nov 25 '15 at 15:49
  • 1
    It's at least related and I came here specifically to check directory, not files. I was trying to figure out if a parameter passed to my program was referencing a directory or file on a remote system, so thanks. – gravy21 Feb 01 '18 at 15:10
7

Actually in my project ls working without loops. I just pass to the ls call path with filename.

private static boolean exists(ChannelSftp channelSftp, String path) {
    Vector res = null;
    try {
        res = channelSftp.ls(path);
    } catch (SftpException e) {
        if (e.id == SSH_FX_NO_SUCH_FILE) {
            return false;
        }
        log.error("Unexpected exception during ls files on sftp: [{}:{}]", e.id, e.getMessage());
    }
    return res != null && !res.isEmpty();
}

For example there a file file.txt with an url sftp://user@www.server.comm/path/to/some/random/folder/file.txt. I pass to function exists path as /path/to/some/random/folder/file.txt

Oleg Svechkarenko
  • 2,508
  • 25
  • 30
3

(This is if you're using the SFTP part of the library, an assumption I made without thinking about it.)

I thought its ls(String path) would accept filenames; I can't check at the moment.

If it doesn't, you don't need to iterate manually; you can use the selector variant:

ls(String path, ChannelSftp.LsEntrySelector selector)
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • 1
    This invocation throws an Exception if the file does not exist, so you need the error handling provided by `Oleg Svechkarenko` or `zelinka` in there answers – Ralph Feb 11 '19 at 09:13
  • 1
    If you use full path to a file and file exists, you will get Vector with one element. If the file doesn't exist, you'll get `com.jcraft.jsch.SftpException`. with id=`ChannelSftp.SSH_FX_NO_SUCH_FILE` – Michal Krasny Sep 03 '20 at 12:51
1
import java.util.ArrayList;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class FileExists {

ChannelExec channelExec = null;
static Channel channel = null;

static String host = "hostname";
static String user = "username";
static String password = "password$";

public static void main(String[] args) {
    String filename = "abc.txt";
    String filepath = "/home/toolinst/ggourav";
    try {
        Channel channel = getChannelSftp(host, user, password);
        channel.connect();
        ChannelSftp channelSftp = (ChannelSftp) channel;
        channelSftp.cd(filepath);
        String path = channelSftp.ls(filename).toString();
        if (!path.contains(filename)) {
            System.out.println("File doesn't exist.");
        } else
            System.out.println("File already exist.");

    } catch (Exception e) {
        e.printStackTrace();
    }

}

private static Channel getChannelSftp(String host, String user, String password) {
    try {
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, 22);
        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
        session.setConfig(config);
        session.setPassword(password);
        session.connect();
        channel = session.openChannel("sftp");

    } catch (Exception e) {
        System.out.println("Failed to get sftp channel. " + e);
    }
    return channel;
}

}

Pierre.Vriens
  • 2,117
  • 75
  • 29
  • 42
Gourav Goutam
  • 81
  • 1
  • 4
  • 1
    Welcome to the site! Answers like this may be useful in content, but providing some sort of explanation or context to the code provided is always helpful. I'd recommend editing your answer to explain a little more in detail about what your code does and how it resolves the problem. This is useful for when future visitors see your answer, as they may not understand your code snippet, but might better understand your explanation, or your explanation of your code snippet could help them solve a similar problem they're having. –  Jun 21 '19 at 16:50
  • please further edit this (update) answer, to explain it as suggested also in the prior comment from @Catch44 – Pierre.Vriens Aug 25 '19 at 09:28
0

you can check by

 if [ -e FILE_NAME ] ; then
    //do something
 fi

or

  if [ -d DIRNAME ]

for directory

or

    if [ -l SYMLINK ]

for softlinks

I hope this helps


Here is an example to run commands on remote machine http://www.jcraft.com/jsch/examples/Exec.java.html

You can very well run ls or a pass a whole script. It's same as copying the script to remote machine and then executing it.

Nishant
  • 54,584
  • 13
  • 112
  • 127