首先大家看看这段java代码的打印结果:
Vector v1 = sftpClient.ls(remoteDerectory);
for (Iterator iterator2 = v1.iterator(); iterator2
.hasNext();) {
SFTPv3DirectoryEntry ob = (SFTPv3DirectoryEntry)
iterator2.next();
System.out.println("--------******************----------");
System.out.println("ob.longEntry is:" + ob.longEntry);
System.out.println("ob.filename is:" + ob.filename);
System.out.println("ob.attributes.isDirectory() is:"
+ ob.attributes.isDirectory());
System.out.println("ob.attributes.size is:"
+ ob.attributes.size);
System.out.println("--------******************----------");
}
}
--------******************----------
ob.longEntry is:drwxr-xr-x 3 root root 4096 Mar 3 09:32 .
ob.filename is:.
ob.attributes.isDirectory() is:true
ob.attributes.size is:4096
--------******************----------
--------******************----------
ob.longEntry is:drwxr-xr-x 3 root root 4096 Mar 3 09:31 ..
ob.filename is:..
ob.attributes.isDirectory() is:true
ob.attributes.size is:4096
--------******************----------
--------******************----------
ob.longEntry is:drwxr-xr-x 2 root root 4096 Mar 3 09:32 t
ob.filename is:t
ob.attributes.isDirectory() is:true
ob.attributes.size is:4096
--------******************----------
--------******************----------
ob.longEntry is:-rw-r--r-- 1 root root 6 Mar 3 09:31 t.txt
ob.filename is:t.txt
ob.attributes.isDirectory() is:false
ob.attributes.size is:6
--------******************----------
故才有之前的方法:
List<String> filelist = new ArrayList<String>();
List<String> direlist = new ArrayList<String>();
direlist.add(remoteDerectory);
定义存放文件和目录的List,其存放的是全路径:
如:
fileLIst:
/usr/local/test/tt.txt
direlist:
/usr/local/test/tt/t
列出所有目录和文件信息:
Vector v = sftpClient.ls(remoteDerectory);
遍历目录和文件信息,存入定义好的对象中:
getUrlPath(sftpClient, filelist, direlist, remoteDerectory);
逆向删除目录和文件:
System.out.println("file list is::");
for (int i = filelist.size() - 1; i > -1; i--) {
System.out.println(filelist.get(i));
sftpClient.rm(filelist.get(i));
}
System.out.println("directory list is::");
for (int i = direlist.size() - 1; i > -1; i--) {
System.out.println(direlist.get(i));
sftpClient.rmdir(direlist.get(i));
}
private static void getUrlPath(SFTPv3Client sftpClient,
List<String> filelist, List<String> direlist, String remoteDerectory)
throws IOException {
Vector v = sftpClient.ls(remoteDerectory);
for (Iterator iterator = v.iterator(); iterator.hasNext();) {
SFTPv3DirectoryEntry object = (SFTPv3DirectoryEntry) iterator
.next();
System.out.println(object.filename);
if (object.attributes.isDirectory()
&& object.filename.indexOf(".") == -1) {
String rderectory = remoteDerectory + "/" + object.filename;
direlist.add(rderectory);
getUrlPath(sftpClient, filelist, direlist, rderectory);
} else if (!object.filename.startsWith(".")
&& !object.filename.endsWith(".")) {
String path = remoteDerectory + "/" + object.filename;
filelist.add(path);
}
}
}
这个方法内部有个递归调用,将所有的文件和目录信息存入对应的对象中;
if (!object.filename.startsWith(".")
&& !object.filename.endsWith("."))
这个判断主要是排除:
--------******************----------
ob.longEntry is:drwxr-xr-x 3 root root 4096 Mar 3 09:31 ..
ob.filename is:..
ob.attributes.isDirectory() is:true
ob.attributes.size is:4096
--------******************----------
类似这样的信息;判断不严格。
我们再看看:
Vector v = sftpClient.ls(remoteDerectory);
for (Iterator iterator = v.iterator(); iterator.hasNext();) {
SFTPv3DirectoryEntry object = (SFTPv3DirectoryEntry) iterator
.next();
为什么Vector中存放的是
SFTPv3DirectoryEntry
这个对象,可以查看源码:
/**
* List the contents of a directory.
*
* @param dirName See the {@link SFTPv3Client comment} for the class for more details.
* @return A Vector containing {@link SFTPv3DirectoryEntry} objects.
* @throws IOException
*/
public Vector ls(String dirName) throws IOException
{
byte[] handle = openDirectory(dirName);
Vector result = scanDirectory(handle);
closeHandle(handle);
return result;
}
继续查看:
Vector result = scanDirectory(handle);
private final Vector scanDirectory(byte[] handle) throws IOException
{
Vector files = new Vector();
while (true)
{
int req_id = generateNextRequestID();
TypesWriter tw = new TypesWriter();
tw.writeString(handle, 0, handle.length);
if (debug != null)
{
debug.println("Sending SSH_FXP_READDIR...");
debug.flush();
}
sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes());
byte[] resp = receiveMessage(34000);
if (debug != null)
{
debug.println("Got REPLY.");
debug.flush();
}
TypesReader tr = new TypesReader(resp);
int t = tr.readByte();
int rep_id = tr.readUINT32();
if (rep_id != req_id)
throw new IOException("The server sent an invalid id field.");
if (t == Packet.SSH_FXP_NAME)
{
int count = tr.readUINT32();
if (debug != null)
debug.println("Parsing " + count + " name entries...");
while (count > 0)
{
SFTPv3DirectoryEntry dirEnt = new SFTPv3DirectoryEntry();
dirEnt.filename = tr.readString(charsetName);
dirEnt.longEntry = tr.readString(charsetName);
dirEnt.attributes = readAttrs(tr);
files.addElement(dirEnt);
if (debug != null)
debug.println("File: '" + dirEnt.filename + "'");
count--;
}
continue;
}
if (t != Packet.SSH_FXP_STATUS)
throw new IOException("The SFTP server sent an unexpected packet type (" + t + ")");
int errorCode = tr.readUINT32();
if (errorCode == ErrorCodes.SSH_FX_EOF)
return files;
throw new SFTPException(tr.readString(), errorCode);
}
}
首先定义了:
Vector files = new Vector();
最后存放的是:
files.addElement(dirEnt);
在看看:SFTPv3DirectoryEntry对象定义:
public class SFTPv3DirectoryEntry
{
/**
* A relative name within the directory, without any path components.
*/
public String filename;
/**
* An expanded format for the file name, similar to what is returned by
* "ls -l" on Un*x systems.
* <p>
* The format of this field is unspecified by the SFTP v3 protocol.
* It MUST be suitable for use in the output of a directory listing
* command (in fact, the recommended operation for a directory listing
* command is to simply display this data). However, clients SHOULD NOT
* attempt to parse the longname field for file attributes; they SHOULD
* use the attrs field instead.
* <p>
* The recommended format for the longname field is as follows:<br>
* <code>-rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer</code>
*/
public String longEntry;
/**
* The attributes of this entry.
*/
public SFTPv3FileAttributes attributes;
其包含了三个基本属性,分别是:
filename 文件或者目录名称;
longEntry 目录(d)权限等基本信息:例如:drwxr-xr-x 2 root root 4096 Mar 3 09:32 t 或者 -rw-r--r-- 1 root root 3 Mar 3 09:31 tt.txt
SFTPv3FileAttributes 定义了entry 属性对象,存放是否是目录,权限等基础信息;
继续查看源码:
public class SFTPv3FileAttributes
{
/**
* The SIZE attribute. <code>NULL</code> if not present.
*/
public Long size = null;
/**
* The UID attribute. <code>NULL</code> if not present.
*/
public Integer uid = null;
/**
* The GID attribute. <code>NULL</code> if not present.
*/
public Integer gid = null;
/**
* The POSIX permissions. <code>NULL</code> if not present.
* <p>
* Here is a list:
* <p>
* <pre>Note: these numbers are all OCTAL.
*
* S_IFMT 0170000 bitmask for the file type bitfields
* S_IFSOCK 0140000 socket
* S_IFLNK 0120000 symbolic link
* S_IFREG 0100000 regular file
* S_IFBLK 0060000 block device
* S_IFDIR 0040000 directory
* S_IFCHR 0020000 character device
* S_IFIFO 0010000 fifo
* S_ISUID 0004000 set UID bit
* S_ISGID 0002000 set GID bit
* S_ISVTX 0001000 sticky bit
*
* S_IRWXU 00700 mask for file owner permissions
* S_IRUSR 00400 owner has read permission
* S_IWUSR 00200 owner has write permission
* S_IXUSR 00100 owner has execute permission
* S_IRWXG 00070 mask for group permissions
* S_IRGRP 00040 group has read permission
* S_IWGRP 00020 group has write permission
* S_IXGRP 00010 group has execute permission
* S_IRWXO 00007 mask for permissions for others (not in group)
* S_IROTH 00004 others have read permission
* S_IWOTH 00002 others have write permisson
* S_IXOTH 00001 others have execute permission
* </pre>
*/
public Integer permissions = null;
/**
* The ATIME attribute. Represented as seconds from Jan 1, 1970 in UTC.
* <code>NULL</code> if not present.
*/
public Integer atime = null;
/**
* The MTIME attribute. Represented as seconds from Jan 1, 1970 in UTC.
* <code>NULL</code> if not present.
*/
public Integer mtime = null;
/**
* Checks if this entry is a directory.
*
* @return Returns true if permissions are available and they indicate
* that this entry represents a directory.
*/
public boolean isDirectory()
{
if (permissions == null)
return false;
return ((permissions.intValue() & 0040000) != 0);
}
/**
* Checks if this entry is a regular file.
*
* @return Returns true if permissions are available and they indicate
* that this entry represents a regular file.
*/
public boolean isRegularFile()
{
if (permissions == null)
return false;
return ((permissions.intValue() & 0100000) != 0);
}
/**
* Checks if this entry is a a symlink.
*
* @return Returns true if permissions are available and they indicate
* that this entry represents a symlink.
*/
public boolean isSymlink()
{
if (permissions == null)
return false;
return ((permissions.intValue() & 0120000) != 0);
}
/**
* Turn the POSIX permissions into a 7 digit octal representation.
* Note: the returned value is first masked with <code>0177777</code>.
*
* @return <code>NULL</code> if permissions are not available.
*/
public String getOctalPermissions()
{
if (permissions == null)
return null;
String res = Integer.toString(permissions.intValue() & 0177777, 8);
StringBuffer sb = new StringBuffer();
int leadingZeros = 7 - res.length();
while (leadingZeros > 0)
{
sb.append('0');
leadingZeros--;
}
sb.append(res);
return sb.toString();
}
}
这个里面基本定义了权限,是否是目录等基本信息;