Seth Kenlon 发布的文章

让用户用命令行选项调整你的 Java 应用程序运行方式。

 title=

通常向终端中输入命令时,无论是启动 GUI 应用程序还是仅启动终端应用程序,都可以使用 命令行选项 options or switches or flags 以下简称选项)来修改应用程序的运行方式。这是 POSIX 规范 设定的标准,因此能够检测和解析选项对 Java 程序员而言是很有用的技能。

Java 中有若干种解析选项的方法,其中我最喜欢用的是 Apache Commons CLI 库,简称 commons-cli

安装 commons-cli

如果你使用类似 Maven 之类的项目管理系统以及 集成开发环境 Integrated Development Environment (简称 IDE),可以在项目属性(比如 pom.xml 配置文件或者 Eclipse 和 NetBeans 的配置选项卡)中安装 Apache Commons CLI 库。

而如果你采用手动方式管理库,则可以从 Apache 网站下载 该库的最新版本。下载到本地的是几个捆绑在一起的 JAR 文件,你只需要其中的一个文件 commons-cli-X.Y.jar(其中 X 和 Y 代指最新版本号)。把这个 JAR 文件或手动或使用 IDE 添加到项目,就可以在代码中使用了。

将库导入至 Java 代码

在使用 commons-cli 库之前,必须首先导入它。对于本次选项解析的简单示例而言,可以先在 Main.java 文件中简单写入以下标准代码:

package com.opensource.myoptparser;

import org.apache.commons.cli.*;

public class Main {
    public static void main(String[] args) {
    // code 
    }
}

至此在 Java 中解析选项的准备工作已经做好了。

在 Java 中定义布尔选项

要实现解析选项,首先要定义应用程序可接收的有效选项。使用 Option(注意是单数)类来创建选项对象,使用 Options(注意是复数)类来追踪项目中创建的所有选项。

首先为选项创建一个组,按照惯例命名为 options

    //code
    Options options = new Options();

接下来,通过列出短选项(即选项名简写)、长选项(即全写)、默认布尔值(LCTT 译注:设置是否需要选项参数,指定为 false 时此选项不带参,即为布尔选项)和帮助信息来定义选项,然后设置该选项是否为必需项(LCTT 译注:下方创建 alpha 对象的代码中未手动设置此项),最后将该选项添加到包含所有选项的 options 组对象中。在下面几行代码中,我只创建了一个选项,命名为 alpha

    //define options
    Option alpha = new Option("a", "alpha", false, "Activate feature alpha");
    options.addOption(alpha);

在 Java 中定义带参选项

有时用户需要通过选项提供 truefalse 以外的信息,比如给出配置文件、输入文件或诸如日期、颜色这样的设置项值。这种情况可以使用 builder 方法,根据选项名简写为其创建属性(例如,-c 是短选项,--config 是长选项)。完成定义后,再将定义好的选项添加到 options 组中:

    Option config = Option.builder("c").longOpt("config")
        .argName("config")
        .hasArg()
        .required(true)
        .desc("set config file").build();
    options.addOption(config);

builder 函数可以用来设置短选项、长选项、是否为必需项(本段代码中必需项设置为 true,也就意味着用户启动程序时必须提供此选项,否则应用程序无法运行)、帮助信息等。

使用 Java 解析选项

定义并添加所有可能用到的选项后,需要对用户提供的参数进行迭代处理,检测是否有参数同预设的有效短选项列表中的内容相匹配。为此要创建命令行 CommandLine 本身的一个实例,其中包含用户提供的所有参数(包含有效选项和无效选项)。为了处理这些参数,还要创建一个 CommandLineParser 对象,我在代码中将其命名为 parser。最后,还可以创建一个 HelpFormatter 对象(我将其命名为 helper),当参数中缺少某些必需项或者用户使用 --help-h 选项时,此对象可以自动向用户提供一些有用的信息。

    // define parser
    CommandLine cmd;
    CommandLineParser parser = new BasicParser();
    HelpFormatter helper = new HelpFormatter();

最后,添加一些条件判断来分析用户提供的选项,我们假设这些选项已经作为命令行输入被获取并存储在 cmd 变量中。这个示例应用程序有两种不同类型的选项,但对这两种类型都可以使用 .hasOption 方法加上短选项名称来检测选项是否存在。检测到一个存在的选项后,就可以对数据做进一步操作了。

try {
    cmd = parser.parse(options, args);
    if(cmd.hasOption("a")) {
    System.out.println("Alpha activated");
    }

    if (cmd.hasOption("c")) {
    String opt_config = cmd.getOptionValue("config");
    System.out.println("Config set to " + opt_config);
    }
} catch (ParseException e) {
    System.out.println(e.getMessage());
    helper.printHelp("Usage:", options);
    System.exit(0);
}

解析过程有可能会产生错误,因为有时可能缺少某些必需项如本例中的 -c--config 选项。这时程序会打印一条帮助信息,并立即结束运行。考虑到此错误(Java 术语中称为异常),在 main 方法的开头要添加语句声明可能的异常:

public static void main(String[] args) throws ParseException {

示例程序至此就大功告成了。

测试代码

你可以通过调整传递给代码的默认参数来在 IDE 中测试应用程序,或者创建一个 JAR 文件并在终端运行测试。这个过程可能会因 IDE 的不同而不同。具体请参阅相应的 IDE 文档,以及我写过的关于如何创建 JAR 文件的文章,或者参考 Daniel Oh 的关于如何使用 Maven 执行同样操作的文章。

首先,省略必需项 -c--config 选项,检测解析器的异常处理:

$ java -jar dist/myapp.jar                 
Missing required option: c
usage: Usage:
 -a,--alpha             Activate feature alpha
 -c,--config <config>   Set config file

然后提供输入选项再进行测试:

java -jar dist/myantapp.jar --config foo -a
Alpha activated
Config set to foo

选项解析

为用户提供选项功能对任何应用程序来说都是很重要的。有了 Java 和 Apache Commons,要实现这个功能并不难。

以下是完整的演示代码,供读者参考:

package com.opensource.myapp;

import org.apache.commons.cli.*;

public class Main {
    
    /**
     * @param args the command line arguments
     * @throws org.apache.commons.cli.ParseException
     */ 
    public static void main(String[] args) throws ParseException {
        // define options
        Options options = new Options();
        
        Option alpha = new Option("a", "alpha", false, "Activate feature alpha");
        options.addOption(alpha);
        
        Option config = Option.builder("c").longOpt("config")
                .argName("config")
                .hasArg()
                .required(true)
                .desc("Set config file").build();
        options.addOption(config);
     
        // define parser
        CommandLine cmd;
        CommandLineParser parser = new BasicParser();
        HelpFormatter helper = new HelpFormatter();

        try {
            cmd = parser.parse(options, args);
            if(cmd.hasOption("a")) {
                System.out.println("Alpha activated");
            }
          
            if (cmd.hasOption("c")) {
                String opt_config = cmd.getOptionValue("config");
                System.out.println("Config set to " + opt_config);
            }
        } catch (ParseException e) {
            System.out.println(e.getMessage());
            helper.printHelp("Usage:", options);
            System.exit(0);
        }
    }
}

使用 Java 和选项

选项使用户可以调整命令的工作方式。使用 Java 时解析选项的方法有很多,其中之一的 commons-cli 是一个强大而灵活的开源解决方案。记得在你的下一个 Java 项目中尝试一下哦。


via: https://opensource.com/article/21/8/java-commons-cli

作者:Seth Kenlon 选题:lujun9972 译者:unigeorge 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

本教程讲述了如何在 Linux 终端中安全地删除文件和文件夹。

 title=

要想使用图形化界面删除计算机上的文件,你可能会直接将文件或文件夹拖拽到 “垃圾箱” 或 “回收站”。或者你也可以选择要删除的文件或文件夹,右键单击并选择 删除

而在终端中删除文件或文件夹时并没有垃圾箱一说(至少默认情况下没有)。在图形化桌面上,Trash(即垃圾箱文件夹)是一个受保护的目录,保护机制可以防止用户不小心将该目录删除,或将其从默认位置移动从而导致找不到它。Trash 本质不过是一个被高度管理的文件夹,因此你可以创建自己的 Trash 文件夹以在终端中使用。

为终端设置一个垃圾箱

在家目录中创建一个名为 Trash 的目录:

$ mkdir ~/Trash

删除文件

要删除文件或文件夹时,使用 mv 命令将文件或文件夹移至 Trash 中:

$ mv example.txt ~/Trash

永久删除文件或文件夹

当你准备从系统中永久删除某个文件或文件夹时,可以使用 rm 命令清除垃圾箱文件夹中的所有数据。通过将 rm 命令指向星号(*),可以删除 Trash 文件夹内的所有文件和文件夹,而不会删除 Trash 文件夹本身。因为用户可以方便且自由地创建目录,所以即使不小心删除了 Trash 文件夹,你也可以再次新建一个。

$ rm --recursive ~/Trash/*

删除空目录

删除空目录有一个专门的命令 rmdir,它只能用来删除空目录,从而保护你免受递归删除错误的影响。

$ mkdir full
$ touch full/file.txt
$ rmdir full
rmdir: failed to remove 'full/': Directory not empty

$ mkdir empty
$ rmdir empty

更好的删除方式

此外还有一些并没有默认安装在终端上的 删除文件命令,你可以从软件库安装它们。这些命令管理和使用的 Trash 文件夹与你在桌面模式使用的是同一个(而非你自己单独创建的),从而使删除文件变得更加方便。

$ trash ~/example.txt
$ trash --list
example.txt
$ trash --empty

via: https://opensource.com/article/21/8/remove-files-linux-terminal

作者:Seth Kenlon 选题:lujun9972 译者:unigeorge 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 mv 命令将一个文件从一个位置移动到另一个位置。

 title=

要在有图形界面的计算机上移动一个文件,你要打开该文件当前所在的文件夹,然后打开另一个窗口导航到你想把文件移到的文件夹。最后,你把文件从一个窗口拖到另一个窗口。

要在终端中移动文件,你可以使用 mv 命令将文件从一个位置移动到另一个位置。

$ mv example.txt ~/Documents

$ ls ~/Documents
example.txt

在这个例子中,你已经把 example.txt 从当前文件夹移到了主目录下的 Documents 文件夹中。

只要你知道一个文件在 哪里,又想把它移到 哪里 去,你就可以把文件从任何地方移动到任何地方,而不管你在哪里。与在一系列窗口中浏览你电脑上的所有文件夹以找到一个文件,然后打开一个新窗口到你想让该文件去的地方,再拖动该文件相比,这可以大大节省时间。

默认情况下,mv 命令完全按照它被告知的那样做:它将一个文件从一个位置移动到另一个位置。如果在目标位置已经存在一个同名的文件,它将被覆盖。为了防止文件在没有警告的情况下被覆盖,请使用 --interactive(或简写 -i)选项。

$ mv -i example.txt ~/Documents
mv: overwrite '/home/tux/Documents/example.txt'?

via: https://opensource.com/article/21/8/move-files-linux

作者:Seth Kenlon 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

学习在 Linux 终端中从一个目录切换到另一个目录。

 title=

要在图形界面中浏览你的计算机上的文件夹,你可能习惯于打开一个窗口来“进入”你的计算机,然后双击一个文件夹,再双击一个子文件夹,如此反复。你也可以使用箭头按钮或按键来回溯。

而要在终端中浏览你的计算机,你可以利用 cd 命令。你可以使用 cd .. 回到 上一级 目录,或者使用 cd ./另一个/文件夹的/路径 来跳过许多文件夹进入一个特定的位置。

你在互联网上已经使用的 URL 的概念,实际上直接来自 POSIX。当你浏览某个网站的一个特定页面时,比如 http://www.example.com/tutorials/lesson2.html,你实际上做的是进入 /var/www/imaginarysite/tutorials/ 目录,并打开一个叫 classic2.html 的文件。当然,你是在 Web 浏览器中打开它的,浏览器会将所有那些看起来奇怪的 HTML 代码解释成漂亮的文本和图片。但这两者的思路是完全一样的。

如果你把你的计算机看成是互联网(或者把互联网看成是计算机会更合适),那么你就能理解如何在你的文件夹和文件中遨游了。如果从你的用户文件夹(你的家目录,或简记为 ~)开始,那么你想切换到的文件夹都是相对于这个文件夹而言的:

$ cd ~/Documents
$ pwd
/home/tux/Documents

$ cd ..
$ pwd
/home/tux

这需要一些练习,但一段时间后,它会变得比你打开和关闭窗口、点击返回按钮和文件夹图标快得多。

用 Tab 键自动补全

键盘上的 Tab 键可以自动补全你开始输入的文件夹和文件的名字。如果你要 cd~/Documents 文件夹,那么你只需要输入 cd ~/Doc,然后按 Tab 键即可。你的 Shell 会自动补全 uments。这不仅仅是一个令人愉快的便利工具,它也是一种防止错误的方法。如果你按下 Tab 键而没有任何东西自动补全,那么可能你 认为 存在于某个位置的文件或文件件实际上并不存在。即使有经验的 Linux 用户也会试图切换到一个当前目录下不存在的文件夹,所以你可以经常使用 pwdls 命令来确认你确实在你认为你在的目录、以及你的当前目录确实包含了你认为它包含的文件。


via: https://opensource.com/article/21/8/navigate-linux-directories

作者:Seth Kenlon 选题:lujun9972 译者:piaoshi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

通过这个 Linux 教程学习如何使用 ls 命令在终端中列出文件。

 title=

要在有图形界面的计算机上列出文件,你通常可以打开一个文件管理器(Linux 上的 “文件”,MacOS 上的 “访达”,Windows 上的 “文件资源管理器”)来查看文件。

要在终端中列出文件,你可以使用 ls 命令来列出当前目录中的所有文件。而 pwd 命令可以告诉你当前所在的目录:

$ pwd
/home/tux
$ ls
example.txt
Documents
Downloads
Music
Pictures
Templates
Videos

你可以通过 --all(简写为 -a) 选项看到隐藏文件:

$ pwd
/home/tux
$ ls --all
.               Downloads
..              .local
.bashrc         Music
.config         Pictures
example.txt     Templates
Documents       Videos

如你所见,列出的前两项是点。单个点(.)实际上是一个元位置,代表 你当前所在的文件夹 。两个点(..)表示你可以从当前位置返回的上级目录。也就是说,当前目录在另一个文件夹中。当你在计算机目录间移动时,你就可以利用这些元位置为自己创建快捷方式,或者增加你的路径的独特性。

文件和文件夹以及如何区分它们

你可能会注意到,文件和文件夹是很难区分的。一些 Linux 发行版有一些漂亮的颜色设置,比如所有的文件夹都是蓝色的,文件是白色的,二进制文件是粉色或绿色的,等等。如果你没有看到这些颜色,你可以试试 ls --color。如果你有色盲症或者使用的不是彩色显示器,你可以使用 --classify 选项替代:

$ pwd
/home/tux/Downloads
$ ls --classify
android-info.txt
cheat/
test-script.sh*

你会发现,文件夹末尾加了一个斜杠(/),以表示它们是文件系统中的某一级目录。而二进制文件,如压缩文件和可执行程序,用星号(*)标记。


via: https://opensource.com/article/21/8/linux-list-files

作者:Seth Kenlon 选题:lujun9972 译者:piaoshi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

下载 sedgrepparted 的速查表来整合新的流程到你的工作中。

 title=

Linux 因其命令闻名,部分原因是 Linux 执行的几乎所有操作都可以从终端调用;另一部分原因是 Linux 是一个高度模块化的操作系统,它的工具被设计用于产生十分确定的结果,在非常了解一些命令后,你可以将这些命令进行奇妙的组合,产生有用的输出。Linux 的学习过程一半是学习命令,另一半是学习如何将这些命令连成有意思的组合。

然而有这么多 Linux 命令需要学习,迈出第一步似乎令人望而生畏。应该先学习哪一个命令?有那些命令需要熟练掌握,又有哪些命令只需要浅尝辄止?认真考虑过这些问题后,我个人不相信有一个通用的答案。对所有人来说,“基本”命令很可能是相同的:

  • ls
  • cd
  • mv

有这些命令你就可以浏览自己的 Linux 文件系统。

但是,除了基本命令,不同行业的“默认”命令有所不同。系统管理员需要 系统自我检查和监测 的工具;艺术家需要 媒体转换图形处理 工具;家庭用户可能想要 PDF 处理日历文档转换 工具。这份列表无穷无尽。

然而一些 Linux 命令由于极其重要能够脱颖而出 —— 或者因为这些命令是每个人不时需要的常用的底层工具,或者因为这些命令是每个人在大多数时间都会觉得有用的万能工具。

这里有三个需要添加到你的列表中的命令。

Sed

用途: sed 是一个任何 Linux 用户都可以从学习中获益的优良通用工具。从表面上看,它只是一个基于终端的“查找和替换”,能够简单快速地纠正多个文档。sed 命令为我节省了打开单个文件、寻找和替换一个单词、保存文件、关闭文件所需要的数个小时(也可能是数天)时间,仅此一条命令就证明了我在学习 Linux 终端的投入是合理的。一旦充分了解 sed,你很有可能发现一个使生活更加轻松的潜在编辑技巧世界。

长处: 命令的长处在于重复。如果你只有一个要编辑的文件,很容易在传统的 文本编辑器打开并进行“查找和替换”。然而,如果要替换 5 或 50 个文件,恰当地使用 sed 命令(可能结合 GNU Parallel 进行加速)可以帮你节省数个小时。

不足: 你需要权衡直接更改期望所花的时间和构建正确的 sed 命令可能需要的时间。使用常见的 sed 's/foo/bar/g' 语法所做的简单编辑通常值得上输入这些命令所花的时间;但是利用保持空间和任何 ed 形式子命令的复杂 sed 命令可能需要高度集中的注意力和多次的试错。事实证明,使用 sed 进行编辑通常是更好的方式。

秘技: 下载我们的 sed 速查表 获取命令的单字母子命令和语法概述的快速参考。

Grep

用途: grep 一词来源于其公认的笨拙描述:全局正则表达式打印。换言之,在文件中(或者其他形式的输入中)找到的任何匹配模式,grep 都会打印到终端。这使得 grep 成为一个强大的搜索工具,尤其擅长处理大量的文本。

你可以使用 grep 查找 URL:

$ grep --only-matching \
  http\:\/\/.* example.txt

你可以使用 grep 查找一个特定的配置项:

$ grep --line-number \
  foo= example.ini
2:foo=true

当然,你还可以将 grep 和其他命令组合:

$ grep foo= example.ini | cut -d= -f2
true

长处: grep 是一个简单的搜索命令,如果你阅读了上面的例子,就已经基本有所了解。为了增强灵活性,你可以使用命令的扩展正则表达式语法。

不足: grep 的问题也是它的长处:它只有搜索功能。一旦你找到想要的内容,可能会面临一个更大的问题 —— 如何处理找到的内容。有时进行的处理可能简单如重定向输出到一个文件,作为过滤后的结果列表。但是,更复杂的使用场景可能需要对结果做进一步处理,或者使用许多类似 awkcurl(凑巧的是,我们也有 curl 速查表)的命令,或者使用现代计算机上你所拥有的数千个其他选项中的任何一个命令。

秘技: 下载我们的 grep 速查表 获取更多命令选项和正则表达式语法的快速参考。

Parted

用途: GNU parted 不是一个常用命令,但它是最强大的硬盘操作工具之一。关于硬盘驱动器的沮丧事实是 —— 数年来你一直忽略它们,直到需要设置一个新的硬盘时,才会想起自己对于格式化驱动器的最好方式一无所知,而此时熟悉 parted 会十分有用。GNU parted 能够创建磁盘卷标,新建、备份、恢复分区。此外,你可以通过命令获取驱动器及其布局的许多信息,并为文件系统初始化驱动器。

长处: 我偏爱 parted 而不是 fdisk 等类似工具的原因在于它组合了简单的交互模式和完全的非交互选项。不管你如何使用 parted,它的命令符合相同的语法,其编写良好的帮助菜单包含了丰富的信息。更棒的是,命令本身是 智能 的 —— 给一个驱动器分区时,你可以用扇区和百分比指明分区的大小,parted 会尽可能计算出更精细的位置存放分区表。

不足: 在很长一段时间内我不清楚驱动器的工作原理,因此切换到 Linux 后,我花费了很长时间学习 GNU parted。GNU parted 和大多数终端磁盘工具假定你已经知晓什么是一个分区、驱动器由扇区组成、初始时驱动器缺少文件系统,需要磁盘卷标和分区表等等知识。硬盘驱动器的基础而不是命令本身的学习曲线十分陡峭,而 GNU parted 并没有做太多的努力来弥补潜在的认知差距。可以说,带你完成磁盘驱动器的基础知识学习不是命令的职责,因为有类似的 图形应用,但是一个聚焦于工作流程的选项对于 GNU parted 可能是一个有用的附加功能。

秘技: 下载我们的 parted 速查表 获取大量子命令和选项的快速参考。

了解更多

这是一些我最喜欢的命令列表,但是其中的命令自然取决于我如何使用自己的计算机。我编写很多命令解释器脚本,因此频繁地使用 grep 查找配置选项,通过 sed 编辑文本。我还会用到 parted,因为处理多媒体项目时,通常涉及很多硬盘驱动器。你可能已经开发了,或者很快就要使用最喜欢的(至少是 频繁使用的)命令开发自己的工作流程。

整合新的流程到日常工作时,我会创建或者下载一个速查表(就像上面的链接),然后进行练习。我们都有自己的学习方式,找出最适合你的方式,学习一个新的必需命令。你对最常使用的命令了解越多,你就越能充分地使用它们。


via: https://opensource.com/article/21/4/linux-cheat-sheets

作者:Seth Kenlon 选题:lujun9972 译者:YungeG 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出