Ganymed SSH-2 for Java系列7之删除远程服务器上的非空目录(方法说明)

本文详细解析了Java代码中使用SFTP客户端进行目录和文件信息的获取、存储及删除的操作过程,包括如何通过SFTPv3DirectoryEntry对象封装目录和文件信息,并通过递归调用实现对目录和文件的逆向删除。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先大家看看这段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));
			}


这个和之前存入list的顺序有关;


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();
	}
}

这个里面基本定义了权限,是否是目录等基本信息;





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值