1. 概述

通常情况下,在Java项目中使用JAR文件时,我们会将其作为外部库直接添加到classpath中,而不会解压它们。然而,有时我们希望将它们放到文件系统中。本教程将探讨如何在命令行中将JAR文件解压到指定目录。我们将以Linux和Bash为例,介绍每种方法。

2. 问题介绍

本文将以GuavaJAR文件为例,其最新版本是guava-31.1-jre.jar。

Java自带了jar命令,用于创建、更新、查看和提取JAR文件。现在,让我们使用jar命令来提取Guava的JAR文件:

$ tree /tmp/test/jarTest
/tmp/test/jarTest
└── guava-31.1-jre.jar

0 directories, 1 file

$ pwd
/tmp/test/jarTest

$ jar xf guava-31.1-jre.jar 

$ tree /tmp/test/jarTest   
/tmp/test/jarTest
├── com
│   └── google
│       ├── common
│       │   ├── annotations
│       │   │   ├── Beta.class
...
27 directories, 2027 files

如上输出所示,我们可以使用jar xf命令来提取JAR文件,且jar命令默认将文件解压到当前目录。

然而,jar命令并不支持将文件解压到指定目录。

接下来,我们将演示如何实现这一功能。

3. 提取前先进入目标目录

我们了解到jar命令默认将给定的JAR文件解压到当前工作目录。

因此,一个解决思路是:如果我们想将JAR文件解压到特定的目标目录,可以在执行jar命令之前先进入目标目录。

3.1. 测试解决方案

首先,我们创建一个新的目录/tmp/test/newTarget

$ mkdir /tmp/test/newTarget

$ tree /tmp/test/newTarget
/tmp/test/newTarget
0 directories, 0 files

然后,进入目标目录并提取Guava的JAR文件:

$ cd /tmp/test/newTarget && jar xf /tmp/test/jarTest/guava-31.1-jre.jar 
$ tree /tmp/test/newTarget
/tmp/test/newTarget
├── com
│   └── google
│       ├── common
│       │   ├── annotations
│       │   │   ├── Beta.class
...

如上例所示,这个想法奏效了。我们已将Guava的JAR文件解压到了期望的目录。

然而,如果我们回顾执行的命令,会发现存在一些不便:

  • 如果是新的目标目录,必须手动创建。
  • cd命令会改变当前工作目录,因此需要使用绝对路径传递JAR文件。
  • 执行命令后,会留在目标目录,而不是最初的起始位置。

那么,我们来看看如何改进我们的解决方案。

3.2. 创建xJarTo()函数

我们可以创建一个shell函数,自动创建目录并调整JAR文件的路径。首先看看函数,然后理解其工作原理:

#!/bin/bash

xJarTo() {
    the_pwd="$(pwd)"
    the_jar="$1"
    the_dir="$2"

    if [[ "$the_jar" =~ ^[^/].* ]]; then
        the_jar="${the_pwd}/$the_jar"
    fi
    echo "Extracting $the_jar to $the_dir ..."
    mkdir -p "$the_dir"
    cd "$the_dir" && jar xf "$the_jar"
    cd "$the_pwd"
}

函数首先将用户的当前工作目录存储在the_pwd变量中。

然后检查JAR文件的路径:

  • 如果以/*开头——绝对路径,我们可以直接使用用户输入;
  • 否则——相对路径。我们需要在用户当前工作目录前添加路径,以便处理绝对路径。

因此,函数可以适应绝对和相对路径的JAR文件。

接下来,我们在进入目标目录之前执行mkdir -p命令。-p选项告诉mkdir命令如果路径中存在缺失的目录,就创建它们。

然后,我们使用cd进入目标目录,并使用准备好的JAR文件路径执行jar xf命令。

最后,我们回到用户的当前工作目录。

3.3. 测试xJarTo()函数

现在我们了解了xJarTo()函数的工作原理,让我们source(/linux/source-command)该函数,测试它是否按预期工作。

首先,测试目标目录是新目录且JAR文件是绝对路径的情况:

$ pwd
/tmp/test

$ xJarTo /tmp/test/jarTest/guava-31.1-jre.jar /tmp/a_new_dir
Extracting /tmp/test/jarTest/guava-31.1-jre.jar to /tmp/a_new_dir ...

$ tree /tmp/a_new_dir
/tmp/a_new_dir
├── com
│   └── google
│       ├── common
│       │   ├── annotations
│       │   │   ├── Beta.class
...
$ pwd
/tmp/test

如上输出所示,函数按预期工作。新目录即刻创建,内容位于/tmp/a_new_dir下。调用函数后,我们仍在/tmp/test目录下。

接着,测试相对路径的JAR文件情况:

$ pwd
/tmp/test/jarTest

$ xJarTo guava-31.1-jre.jar /tmp/another_new_dir
Extracting /tmp/test/jarTest/guava-31.1-jre.jar to /tmp/another_new_dir ...

$ tree /tmp/another_new_dir
/tmp/another_new_dir
├── com
│   └── google
│       ├── common
│       │   ├── annotations
│       │   │   ├── Beta.class
...

$ pwd
/tmp/test/jarTest

这次,由于我们在/tmp/test/jarTest下,直接将guava-31.1-jre.jar传递给函数。事实证明,函数也完成了任务。

4. 使用其他解压缩工具

JAR文件使用ZIP压缩。因此,所有解压缩工具都可以提取JAR文件。如果系统上有一个支持将文件解压到指定目录的解压缩工具,问题就能得到解决。

这种方法需要系统上至少有一个可用的解压缩工具。如果没有,我们需要安装。值得注意的是,在系统上安装包通常需要rootsudo权限

接下来,以unzip为例,展示流行的yumapt包管理器的安装命令:

# apt
sudo apt install unzip

# yum
sudo yum install unzip

unzip命令支持-d选项,将ZIP存档解压到不同的目录:

$ unzip guava-31.1-jre.jar -d /tmp/unzip_new_dir
$ tree /tmp/unzip_new_dir
/tmp/unzip_new_dir
├── com
│   └── google
│       ├── common
│       │   ├── annotations
│       │   │   ├── Beta.class
...

如我们所见,unzip -d将JAR文件解压到指定目录。

5. 总结

在这篇文章中,我们学习了两种将JAR文件解压到指定目录的方法。

一种方法是创建一个shell函数来包装标准的jar命令。另一种方法是,如果系统上已有其他解压缩工具,如unzip,我们可以利用它们的相应选项将JAR内容解压到所需的目录。