博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手把手教你做一个Shell命令窗口
阅读量:6658 次
发布时间:2019-06-25

本文共 15376 字,大约阅读时间需要 51 分钟。

这是一个类似于win下面的cmd打开后的窗口,可以跨平台使用,可以在win和linux下面同时使用,主要功能如下:

首先我们需要把这些功能的目录写出来,通过写一个死循环,让其每次回车之后都可以保持同样的标题:如,/home/admin1>:

	String userPath = System.getProperty("user.home");		Scanner sc = new Scanner(System.in);
// 死循环		while (true) {			System.out.println(userPath + ">:");			String command = sc.nextLine().trim();			// command是用户输入的命令,这种命令有的会改变userPath的值			if ("exit".equals(command)) {				// 退出程序,打断循环				break;			} else if ("help".equals(command)) {				// 使用FileInputStream来读取 help.txt文件				helpOp();			} else if ("date".equals(command)) {				dateOp();			} else if (command != null && !"".equals(command)					&& command.startsWith("dir")) {				// command:dir显示userPath下的内容				dirOp(userPath, command);			} else if (command != null && !"".equals(command)					&& command.startsWith("cat")) {				catOp(command); // cat绝对路径			} else if (command != null && !"".equals(command)					&& command.startsWith("type")) {				typeOp(command); // 绝对路径			} else if (command != null && !"".equals(command)					&& command.startsWith("md")) {				mdOp(userPath, command); // 相对路径			} else if (command != null && !"".equals(command)					&& command.startsWith("ren")) {				renOp(userPath, command); // 原文件的相对路径名 新文件名 ren/home/a/a.txt											// /home/a/a/b.txt			} else if (command != null && !"".equals(command)					&& command.startsWith("rd")) {				rdOp(userPath, command); // 目录相对路径名			} else if (command != null && !"".equals(command)					&& command.startsWith("del")) {				delOp(userPath, command); // 文件相对路径名			} else if (command != null && !"".equals(command)					&& command.startsWith("copy")) {				copyOp(userPath, command); // 文件相对路径 绝对路径			} else if (command != null && !"".equals(command)					&& command.startsWith("cut")) {				cutOp(userPath, command); // 原文件的相对路径名 相对路径			} else if (command != null && !"".equals(command)					&& command.startsWith("tree")) {				treeOp(userPath); // 输出当前目录下的所有文件 递归			} else if (command != null && !"".equals(command)					&& command.startsWith("cd")) {				userPath = cdOp(userPath, command); // cd. cd.. cd/ cd 目录 有返回值的			} else {				System.out.println("找不到这条命令");			}		}
当然,为了做到跨平台使用,我们可以先定义一下平台:

public final static int OS_TYPE_LINUX = 1; // linux操作系统

public final static int OS_TYPE_WINDOWS = 2; // window操作系统

我们还需要拿到操作系统的名字,当然首先我们来看一下操作系统的详细信息,我们可以使用System.getProperties()来查看系统的所有信息,这个时候我们就会发现,user.home就是我们的系统名,所以我们要把这个拿来使用。

// 区分操作系统	private static int getSystemInfo() {		// Properties就是一个键值对		// Properties p=System.getProperties(); //System类当中存有当前系统的所有信息		// Set
> set=p.entrySet(); //entry:键值对 Set:集合 // Iterator
> its=set.iterator(); //迭代器 // while(its.hasNext()){ //使用迭代器取出集合中的第一个元素,hasNext()返回true // Entry
entry=its.next(); //取出 // System.out.println(entry.getKey()+":"+entry.getValue()); // } String osName = System.getProperty("os.name"); if (osName.toLowerCase().indexOf("linux") >= 0) { return OS_TYPE_LINUX; } else if (osName.toLowerCase().indexOf("windows") >= 0) { return OS_TYPE_WINDOWS; } else { return -1; } }

如果你想查看一下你盘符的容量,我们可以这样做。

// 显示版权	private static void showCopyRight() {		int ostype = getSystemInfo();		if (ostype == OS_TYPE_LINUX) {			System.out.println("ubuntu linux zp");		} else if (ostype == OS_TYPE_WINDOWS) {			System.out.println("Micrsoft windows zp");			System.out.println("Copyright by (2016-2028)");		}		System.out.println("当前系统的盘符:");		File[] fs = File.listRoots();		System.out.println("盘符名\t总大小\t剩余空间:");		for (File file : fs) {			System.out.println(file.getAbsolutePath() + "\t"					+ getSizeInPrety(file.getTotalSpace()) + "\t"					+ getSizeInPrety(file.getFreeSpace()));		}	}
哦!好吧,如果只是这样写,那么显示出来的都是k为大小的,所以我们还要判断一下,把大小显示为G,M,K,B等

private static String getSizeInPrety(long size) {		if (size / 1024 / 1024 / 1024 / 1024 > 0) {			return size / 1024 / 1024 / 1024 / 1024 + "T";		} else if (size / 1024 / 1024 / 1024 > 0) {			return size / 1024 / 1024 / 1024 + "G";		} else if (size / 1024 / 1024 > 0) {			return size / 1024 / 1024 + "M";		} else if (size / 1024 > 0) {			return size / 1024 + "K";		} else {			return size + "B";		}	}
好了,言归正传,我们开始写以上要实现的14条命令。

1、先来写help好了,这样我们就可以看一下帮助了(在不知道有哪些命令的情况下),既然想写help,那么我们就先把help.txt这个文档准备好,然后通过 使用FileInputStream来读取 help.txt文件。最后把这个显示出来就可以了。

private static void helpOp() throws IOException {		// 使用FileInputStream来读取 help.txt文件		// 通过test1的字节码类,找到它的字节码加载器,这个加载器从bin目录开始扫描,查找help.txt文件,再自动以流的方式加载它		InputStream fis = test1.class.getClassLoader().getResourceAsStream(				"help.txt");		// File filename=new		// File(System.getProperty("java.class.path")+File.separator+"help.txt");		// FileInputStream fis = new FileInputStream(filename);		// 第三步:操作!		byte[] buff = new byte[1024];		int len = -1;// 定义缓冲区		while ((len = fis.read(buff, 0, buff.length)) != -1) {			String s = new String(buff, 0, len, "gbk");			System.out.println(s);		}		// 第四步:关闭资源(字符流必须关闭资源,因为它中间有缓冲区!对于字节流可以不用关闭,但是还是建议写上,习惯!)		fis.close();	}
2、然后我们写一下退出吧!纳尼,退出还需要写么,根本不需要好吧,我在前面已经写了,直接break就好了啊,你说你是不是傻
偷笑!你自己看我的第一段代码!

3、既然如此,那我们就来写一下date吧,这个可以用来查看系统时间。用SimpleDateFormat来格式化一个时间。

private static void dateOp() {		// TODO Auto-generated method stub		Date d = new Date();		SimpleDateFormat sd = new SimpleDateFormat("yyyy-M-d HH:mm:ss E");		String s = sd.format(d);// 这个方法继承于SimpleDateFormat的父类DateFormat类!		System.out.println(s);	}
4、那我们再来看一下dir命令吧!dir是可以查看所有的文件和目录的哦,注意不要查看路径太深的文件夹,不然的话,嘿嘿,会循环调用很久哒!这里我们可以统计一下总共有多少个文件和目录,然后还可以判断一下文件的权限rwx,当然,还可以计算一下大小啦,那么我们就可以调用前面说过的getSizeInPrety()方法来格式化一下G,M,K等的大小。
private static void dirOp(String userPath, String command) {		String[] contents = command.split(" ");		if (contents.length == 2) {			// 如果长度为2,就显示userPath下的内容			userPath = contents[1];		}		// y用file类来完成取到这个目录的信息		File f = new File(userPath);		File[] fs = f.listFiles();		int totalFile = 0;		int totalDir = 0;		long totalFileSize = 0;		if (fs != null && fs.length > 0) {			for (File file : fs) {				long time = file.lastModified();				Date d = new Date();				SimpleDateFormat sd = new SimpleDateFormat("yyyy-M-d HH:mm");				String timeString = sd.format(time);				// 权限				String read = file.canRead() ? "r" : "-";				String write = file.canWrite() ? "w" : "-";				String execute = file.canExecute() ? "x" : "-";				// 文件还是目录				String fileorDir = file.isFile() ? "\t" : "
"; // 取大小 long fileSize = file.isFile() ? file.length() : 0; String fileSizeString = "\t"; if (file.isFile()) { fileSizeString = getSizeInPrety(fileSize); totalFile++; totalFileSize += fileSize; } else { totalDir++; } System.out.println(timeString + "\t\t" + read + write + execute + "\t" + fileorDir + "\t" + fileSizeString + file.getName()); } } System.out.println("总共有:" + totalFile + "个文件," + totalDir + "个目录"); }
5、那cat命令也类似,

private static void catOp(String command) {		// 解析command中的文件		String[] contents = command.split(" ");		String filePath = null;		if (contents.length == 2) {			// 如果长度为2,就显示userPath下的内容			filePath = contents[1];		}		// 用file类来完成取到这个目录的信息		File f = new File(filePath);		if (f.exists() == false || f.isFile() == false) {			System.out.println(f.getName() + "不是一个有效文件,无法读取");			return;		}		FileReader fr = null;		try {			fr = new FileReader(f);			BufferedReader br = new BufferedReader(fr);			String line = null;			int num = 0;			while ((line = br.readLine()) != null) {				num++;				System.out.println(num + "\t" + line);			}		} catch (Exception e) {			e.printStackTrace();		} finally {			try {				fr.close();			} catch (IOException e) {				e.printStackTrace();			}		}	}
6、type的话呢,好像也差不多。

private static void typeOp(String command) throws IOException {		// TODO Auto-generated method stub		// 使用BuffedInputStream来完成		// 解析command中的文件		String[] strs = command.split(" ");		if (strs == null || strs.length != 2) {			System.out.println(command + "格式,标准格式:type 文件的绝对路径,请确认后重新输入");			return;		}		File file = new File(strs[1]);		if (file.exists() == false) {			System.out.println(file.getAbsolutePath() + "文件不存在");			return;		}		if (file.isFile() == false) {			System.out.println(file.getAbsolutePath() + "不是一个可以读取的文件");			return;		}		InputStream iis = null;		try {			iis = new BufferedInputStream(new FileInputStream(file));			byte[] bs = new byte[1024];			int length = -1;			while ((length = iis.read(bs, 0, bs.length)) != -1) {				String s = new String(bs, 0, length, "gbk");				System.out.println(s);			}		} catch (Exception e) {			// TODO Auto-generated catch block			e.printStackTrace();		} finally {			try {				iis.close();			} catch (IOException e) {				e.printStackTrace();			}		}	}
7、现在,我们就可以来看一下如何创建目录的吧!这种的话如果不会一定要多看一些API文档了。

private static void mdOp(String userPath, String command) {		// 在userPath下面创建一个目录 md/a/b/c md/a		// File类中的mkdirs()		String[] strs = command.split(" ");		if (strs == null || strs.length != 2) {			System.out.println(command + "格式,标准格式:md  文件的相对路径,请确认后重新输入");			return;		}		File f = new File(userPath, strs[1]);		if (f.exists()) {			System.out.println("文件已存在,无需创建");			return;		}		// 创建目录		System.out.println(f.mkdir() ? "创建目录成功" : "创建目录失败");		System.out.println();}
8、重命名一下文件。主要是调用一下renameTo()方法。
private static void renOp(String userPath, String command) {		// TODO Auto-generated method stub		// File类的renameTo()		String[] strs = command.split(" ");		// 读取command格式是否正确		if (strs == null || strs.length != 3) {			System.out.println(command					+ "格式,标准格式:ren  原文件的相对路径    新文件相对路径名,请确认后重新输入");			return;		}		// 创建一个file表示原文件 new File(userPath,新文件相对路径)		File old = new File(userPath, strs[1]);		// 判断原文件是否存在,不存在则返回		if (old.exists() == false) {			System.out.println(old.getAbsolutePath() + "不存在,请确认后输入");			return;		}		// 判断新文件是否存在,若存在,则返回		File newfile = new File(userPath, strs[2]);		if (newfile.exists()) {			System.out.println(newfile.getAbsolutePath() + "已存在,不能重名");			return;		}		// 将原文件改名为新文件		old.renameTo(newfile);		System.out.println("重命名成功");		System.out.println();	}
9、删除目录,使用rd命令,当然,这种方法我个人是感觉不太好的,因为假如这个目录下面不是空目录就不能删除。

private static void rdOp(String userPath, String command) {		// TODO Auto-generated method stub		// 删目录		String[] strs = command.split(" ");		// 读取command格式是否正确		if (strs == null || strs.length != 2) {			System.out.println(command + "格式,标准格式:rd   目录的相对路径,请确认后重新输入");			return;		}		// 创建一个文件 new File(userPath,strs[1]);		File f = new File(userPath, strs[1]);		// 判断是否存在,是否为目录		if (f.exists() == false) {			System.out.println(f.getAbsolutePath() + "不存在,无法删除");			return;		}		// 判断这个目录是否为空目录,空目录才可以删除		File[] fs = f.listFiles();		if (fs != null && fs.length > 0) {			System.out.println(f.getAbsolutePath() + "不是空目录,不能删除");			return;		}		// 若是空目录,则删除		boolean result = f.delete();		// 显示删除成功		System.out.println(result ? "删除" + f.getName() + "成功" : "删除"				+ f.getName() + "失败");}
所以我们可以来看一下方法2,就是可以循环把整个目录一起删除掉,总之,慎用这条命令,一下小心你可能会删除掉有用下信息哦!

		private static void rdOp(String userPath, String command) {		  String[] contents = command.split(" "); String filePath = null; if		 (contents.length == 2) { // 如果长度为2,就显示userPath下的内容 filePath =		  contents[1]; } File dir = new File(filePath);// 定义文件路径		 deleteFile(dir);		 	}		  private static void deleteFile(File dir) { // TODO Auto-generated method		  File[] subFiles = dir.listFiles(); for (File file : subFiles) { if	  (file.isFile()) { file.delete(); System.out.println("已成功删除文件"); } else {	  deleteFile(file); } } dir.delete(); System.out.println("已成功删除文件夹"); }

10、del就是用来删除文件的。主要就是调用了delete()方法。

private static void delOp(String userPath, String command) {		// TODO Auto-generated method stub		// 删除文件		String[] strs = command.split(" ");		// 读取command格式是否正确		if (strs == null || strs.length != 2) {			System.out.println(command + "格式,标准格式:del   文件的相对路径,请确认后重新输入");			return;		}		// 创建一个文件 new File(userPath,strs[1]);		File f = new File(userPath, strs[1]); // 定义文件路径		// 判断是否存在,是否为目录		if (f.exists() == false) {			System.out.println("文件不存在");			return;		}		if (f.isFile() == false) {			System.out.println("不是文件,不能删除");			return;		}		// 判断是否文件,是则删除		boolean result = f.delete();		// 显示删除成功		System.out.println(result ? "删除" + f.getName() + "成功" : "删除"				+ f.getName() + "失败");}
11、tree命令,用来按层级打印输出路径。

private static void treeOp(String userPath) {	tree(userPath, 1);	}	//递归调用	private static void tree(String path, int level) {		StringBuffer sb = new StringBuffer();		for (int i = 0; i < level; i++) {			sb.append("      ");		}		File f = new File(path);		File[] fs = f.listFiles();		System.out.println(sb.toString() + f.getName());		if (fs != null && fs.length > 0) {			for (File file : fs) {				if (file.isFile()) {					System.out							.println(sb.toString() + "     " + file.getName());				} else {					tree(file.getAbsolutePath(), level + 1);				}			}		}	}
12、copy,还有一个磨人的小妖精,就是这个命令啦!虽然就是用了一个 FileOutputStream来输入输出文本文件内容而已。

private static void copyOp(String userPath, String command) {		String[] strs = command.split(" ");		// 读取command格式是否正确		if (strs == null || strs.length != 3) {			System.out.println(command					+ "格式,标准格式:copy   原文件的相对路径  新文件的绝对路径名,请确认后重新输入");			return;		}		// 创建一个file表示原文件 new File(userPath,新文件相对路径)		File old = new File(userPath, strs[1]);		// 判断原文件是否存在,不存在则返回		if (old.exists() == false) {			System.out.println(old.getAbsolutePath() + "不存在,请确认后输入");			return;		}		// 判断新文件是否存在,若存在,则返回		File newfile = new File(userPath, strs[2]);		if (newfile.exists()) {			System.out.println(newfile.getAbsolutePath() + "已存在,不能复制");			return;		}		// 判断原文件和新文件是否重复		if (old.equals(newfile)) {			System.out.println("目录文件夹是源文件夹的子文件夹");		} else {			copy(old, newfile);		}	}	private static void copy(File old, File newfile) {		// TODO Auto-generated method stub				try (InputStream is = new FileInputStream(old);				OutputStream os = new FileOutputStream(newfile);) {			byte[] b = new byte[1024];			int len;			while ((len = is.read(b)) != -1) {				os.write(b);			}		} catch (IOException e) {			e.printStackTrace();		}		System.out.println("复制成功");	}
13、那么既然,我们前面写了copy和delete,就可以综合使用这两个来写一下cut命令咯!

private static void cutOp(String userPath, String command) {		// TODO Auto-generated method stub				copyOp(userPath, command);     //		String[] strs = command.split(" ");		File old = new File(userPath, strs[1]);		old.delete();		System.out.println("剪切成功");	}
14、最后就只剩下cd命令了,就是需要每次可以使用cd. cd.. cd/ cd 来切换目录。

private static String cdOp(String userPath, String command) {		// TODO Auto-generated method stub		if (command.equals("cd")) {			return userPath;		}		if (command.equals("cd .")) {			return userPath;		}		String[] strs = command.split(" ");		if (strs == null || strs.length != 2) {			System.out.println("命令格式错误,正确格式是:cd 路径表示法");			return userPath;		}		File file = new File(userPath); // 当前路径		if (command.equals("cd ..")) {			if(file.getParent()!=null){   //判断父路径是否为空				return file.getParent();			}					}		if (command.equals("cd /")) {			return getRoot(userPath); 		}		File f = new File(strs[1]);		if (f.exists() && f.isDirectory()) {			return f.getAbsolutePath();		}		System.out.println(strs[1] + "路径异常");		return userPath;	}	private static String getRoot(String userPath) {		int system_type = getSystemInfo();		if (system_type == OS_TYPE_LINUX) {			return "/";		} else {			int last = userPath.indexOf(":\\" + 2);			String path = userPath.substring(0, last);			return path;		}	}
以上就基本实现了一个shell命令窗口的功能了,还有其他的功能,你也来挑战一下吧!

总结:本文主要介绍了shell命令窗口的基本命令的书写,采用java来重写一些基本命令,对文件输入输出流的使用由了进一步的使用,综合了各种循环,判断,各种流的使用,以及API的部分常用语法的使用。

源码地址:https://github.com/sdksdk0/Shell。

转载于:https://www.cnblogs.com/xiaowangba/p/6314849.html

你可能感兴趣的文章
JSF页面中的JS取得受管bean的数据(受管bean发送数据到页面)
查看>>
桥接模式
查看>>
leetcode 627. Swap Salary
查看>>
【待填坑】http和https的概念和区别
查看>>
Callable和Runnable和FutureTask
查看>>
ASP.net WebAPI 上传图片
查看>>
hello openwrt
查看>>
【Flex教程】#009 As/typeof /instanceof /is的作用
查看>>
关于学习程序设计
查看>>
关于Git无法提交 index.lock的解决办法(学)
查看>>
模拟 html radio 的单选效果
查看>>
SPOJ 8073 The area of the union of circles (圆并入门)
查看>>
关于互联网商业模式的一点思考
查看>>
实现待办事项网站回顾
查看>>
做产品也要造概念,讲故事,用优雅的措辞美化自己
查看>>
CPU多级缓存与缓存一致性
查看>>
【转载】#458 Errors While Converting Between enum and Underlying Type
查看>>
checked、disabled在原生、jquery、vue下不同写法
查看>>
android php mysql
查看>>
Java中的接口
查看>>