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

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

<span style="white-space:pre">	</span>String userPath = System.getProperty("user.home");
<span style="white-space:pre"> </span>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<Entry<Object,Object>> set=p.entrySet(); //entry:键值对 Set:集合
// Iterator<Entry<Object,Object>> its=set.iterator(); //迭代器
// while(its.hasNext()){ //使用迭代器取出集合中的第一个元素,hasNext()返回true
// Entry<Object,Object> 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" : "<dir>";
// 取大小
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();<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

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() + "失败");<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

所以我们可以来看一下方法2,就是可以循环把整个目录一起删除掉,总之,慎用这条命令,一下小心你可能会删除掉有用下信息哦!

<span style="white-space:pre">		private static void rdOp(String userPath, String command) {</span>
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() + "失败");<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

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。

手把手教你做一个Shell命令窗口的更多相关文章

  1. R数据分析:跟随top期刊手把手教你做一个临床预测模型

    临床预测模型也是大家比较感兴趣的,今天就带着大家看一篇临床预测模型的文章,并且用一个例子给大家过一遍做法. 这篇文章来自护理领域顶级期刊的文章,文章名在下面 Ballesta-Castillejos ...

  2. 手把手教你做一个原生js拖动滑块【兼容PC和移动端】

    废话少说: 在PC端可以用mousedown来触发一个滑块滑动的效果,但在手机上,貌似无法识别这个事件,但手机上有touchstart事件,可以通过一系列"touch"事件来替代P ...

  3. Android应用系列:手把手教你做一个小米通讯录(附图附源码)

    前言 最近心血来潮,突然想搞点仿制品玩玩,很不幸小米成为我苦逼的第一个试验品.既然雷布斯的MIUI挺受欢迎的(本人就是其的屌丝用户),所以就拿其中的一些小功能做一些小demo来玩玩.小米的通讯录大家估 ...

  4. Vue+ElementUI: 手把手教你做一个audio组件

    目的 本项目的目的是教你如何实现一个简单的音乐播放器(这并不难) 本项目并不是一个可以用于生产环境的element播放器,所以并没有考虑太多的兼容性问题 本项目不是ElementUI的一个音频插件,只 ...

  5. netty系列之:小白福利!手把手教你做一个简单的代理服务器

    目录 简介 代理和反向代理 netty实现代理的原理 实战 总结 简介 爱因斯坦说过:所有的伟大,都产生于简单的细节中.netty为我们提供了如此强大的eventloop.channel通过对这些简单 ...

  6. 手把手教你做一个python+matplotlib的炫酷的数据可视化动图

    1.效果图 2.注意: 上述资料是虚拟的,为了学习制作动图,构建的. 仅供学习, 不是真实数据,请别误传. 当自己需要对真实数据进行可视化时,可进行适当修改. 3.代码: #第1步:导出模块,固定 i ...

  7. UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包

    背景 项目上需要做UWP的自动安装包,在以前的公司接触的是TFS来做自动build. 公司要求用Jenkins来做,别笑话我,之前还真不晓得这个东西. 会的同学请看一下指出错误,不会的同学请先自行脑补 ...

  8. 只有20行Javascript代码!手把手教你写一个页面模板引擎

    http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...

  9. iOS回顾笔记(05) -- 手把手教你封装一个广告轮播图框架

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

随机推荐

  1. No mapping found for HTTP request with URI [/user/login.do] in DispatcherServlet with name 'dispatcher'错误

    1.警告的相关信息 七月 24, 2017 3:53:04 下午 org.springframework.web.servlet.DispatcherServlet noHandlerFound警告: ...

  2. JavaScript数据结构与算法(六) 链表的实现

    // 链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的.每个 // 元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成.下图展 // 示了一个链表的 ...

  3. 网易云安全两篇论文入选计算机视觉顶级会议ICCV

    本文由  网易云发布. 10月22日至29日,全球计算机视觉顶尖专家们共聚威尼斯,参加ICCV2017国际计算机视觉大会,就领域内最新成果展开集中研讨,大会论文集也代表了计算机视觉领域最新的发展方向和 ...

  4. Shell自学之运算符和echo(W3C)

    上面理论知识,最下面有我做的测试的例子: 10.Shell运算符 expr是一款表达式计算工具,使用它能完成表达式的求值操作 例:val=`expr 2 + 2`;echo "${val}& ...

  5. codeforces 888G Xor-MST

    You are given a complete undirected graph with n vertices. A number ai is assigned to each vertex, a ...

  6. 计蒜客NOIP模拟赛D2T3 数三角形

    刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决.给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色.现在,洁洁需要给这张图的多样性进行打分. ...

  7. bzoj 5285: [Hnoi2018]寻宝游戏

    Description Solution 把输入的 \(n\) 个二进制数看作一个大小为 \(n*m\) 的矩阵 把每一列压成一个二进制数,其中最高位是最下面的元素 然后就有了 \(m\) 个二进制数 ...

  8. ubuntu 16.04常见错误--Could not get lock /var/lib/dpkg/lock解决

    我的博客 ubuntu常见错误--Could not get lock /var/lib/dpkg/lock解决 通过终端安装程序sudo apt-get install xxx时出错: E: Cou ...

  9. Java并发编程:JMM(Java内存模型)和volatile

    1. 并发编程的3个概念 并发编程时,要想并发程序正确地执行,必须要保证原子性.可见性和有序性.只要有一个没有被保证,就有可能会导致程序运行不正确. 1.1. 原子性 原子性:即一个或多个操作要么全部 ...

  10. Android编写点击TextView拨打电话

    在任何一个电商平台都会有点击了手机号码会拨打出一个电话 那么高如何实现这个功能,我们下来分析下原理 当我们点击了一个电话号码后,会弹出一个Dialog显示是否拨打次电话号码,点击确定拨打号码,点击取消 ...