如何使用Ganymed的SCPClient复制目录?

时间:2011-07-14 16:06:16

标签: java ssh

我需要以递归方式将目录(在本例中为C:\ test)复制到远程主机。我尝试了显而易见的事实:

conn.connect();
conn.authenticateWithPassword("user", "pw");
SCPClient scp = conn.createSCPClient();
scp.put("C:/test", "~/test");
conn.close();

但这会产生错误:

java.io.IOException: Error during SCP transfer.
    at ch.ethz.ssh2.SCPClient.put(SCPClient.java:577)
    at ch.ethz.ssh2.SCPClient.put(SCPClient.java:535)
    at ch.ethz.ssh2.SCPClient.put(SCPClient.java:430)
    at Test.Test.main(Test.java:57)
Caused by: java.io.FileNotFoundException: C:\test (Access is denied)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(Unknown Source)
    at ch.ethz.ssh2.SCPClient.sendFiles(SCPClient.java:190)
    at ch.ethz.ssh2.SCPClient.put(SCPClient.java:573)
    ... 3 more

我错过了什么,或者Ganymed真的只能复制单个文件,而不是目录吗?我应该exec()在shell上使用适当的scp命令吗?

1 个答案:

答案 0 :(得分:3)

在挖掘了源代码的相关部分后,我相当肯定答案是“你没有”。

将一个或多个文件名作为参数的所有put()方法最终都会调用私有sendFiles()方法来实际发送文件。此方法从每个文件名创建一个File对象,然后从每个文件创建一个FileInputStream对象。当然,FileInputStream的构造函数会抛出FileNotFoundException“如果文件不存在,是目录而不是常规文件,或者由于某些其他原因不能开放阅读。“ (并且,显然,它并不总是使用正确的错误消息抛出它。)


编辑:虽然公平地说,复制目录并不是很难推出自己的递归函数:

private static void putDir(Connection conn, String localDirectory, String remoteTargetDirectory, String mode) throws IOException {
    final String[] fileList = curDir.list();
    for (String file : fileList) {
        final String fullFileName = localDirectory + "/" + file;
        if (new File(fullFileName).isDirectory()) {
            final String subDir = remoteTargetDirectory + "/" + file;
            Session sess = conn.openSession();
            sess.execCommand("mkdir " + subDir);
            sess.waitForCondition(ChannelCondition.EOF, 0);
            putDir(conn, fullFileName, subDir, mode);
        }
        else {
            SCPClient scpc = conn.createSCPClient();
            scpc.put(fullFileName, remoteTargetDirectory, mode);
        }
    }
}