使用 bash,如何从目录中的所有文件创建类路径?

2022-08-31 14:55:11

对于bash大师来说,这将是一个非常简单的免费赠品:

问题

使用 bash,如何从目录中的所有文件创建类路径?


给定一个目录:

LIB=/path/to/project/dir/lib

只包含 *.jar 文件,例如:

junit-4.8.1.jar
jurt-3.2.1.jar
log4j-1.2.16.jar
mockito-all-1.8.5.jar

我需要创建一个冒号分隔的类路径变量,格式为:

CLASSPATH=/path/to/project/dir/lib/junit-4.8.1.jar:/path/to/project/dir/lib/jurt-3.2.1.jar:/path/to/project/dir/lib/log4j-1.2.16.jar:/path/to/project/dir/lib/mockito-all-1.8.5.jar

一些几乎表达了我正在寻找的逻辑的seudo代码将大致如下:

for( each file in directory ) {
   classpath = classpath + ":" + LIB + file.name
}

通过 bash 脚本完成此操作的简单方法是什么?


答案 1

新答案
(2012年10月)

无需手动生成类路径列表。Java 支持对包含 jar 文件的目录使用方便的通配符语法。

java -cp "$LIB/*"

(请注意,位于引号*

说明来自 :man java

为了特别方便,包含基名 * 的类路径元素被视为等效于指定具有扩展名的目录中所有文件的列表,或者(java 程序无法区分两个调用之间的区别)。.jar.JAR

例如,如果目录 foo 包含 和 ,则类路径元素将扩展为 a ,除非 jar 文件的顺序未指定。指定目录中的所有 jar 文件,甚至是隐藏的 jar 文件,都包含在列表中。仅由 的类路径条目展开为当前目录中所有 jar 文件的列表。环境变量(如果已定义)将以类似的方式展开。任何类路径通配符扩展都会在 Java 虚拟机启动之前发生 — 除非通过查询环境,否则任何 Java 程序都不会看到未展开的通配符。a.jarb.JARfoo/*A.jar:b.JAR*CLASSPATH


旧答案

简单但不完美的解决方案:

CLASSPATH=$(echo "$LIB"/*.jar | tr ' ' ':')

有一个轻微的缺陷,因为这将不能正确处理带有空格的文件名。如果这很重要,请尝试这个稍微复杂的版本:

更好

CLASSPATH=$(find "$LIB" -name '*.jar' -printf '%p:' | sed 's/:$//')

这只在你的 find 命令支持时才有效(就像 GNU 一样)。-printffind

如果您没有 GNU ,就像在 Mac OS X 上一样,您可以改用:findxargs

CLASSPATH=$(find "." -name '*.jar' | xargs echo | tr ' ' ':')

最好?

另一种(更奇怪的)方法是更改字段分隔符变量 。这看起来很奇怪,但对所有文件名都很好,并且只使用shell内置。$IFS

CLASSPATH=$(JARS=("$LIB"/*.jar); IFS=:; echo "${JARS[*]}")

解释:

  1. JARS设置为文件名数组。
  2. IFS更改为 。:
  3. 数组将回显,并用作数组条目之间的分隔符。这意味着文件名之间用冒号打印。$IFS

所有这些都是在子壳中完成的,因此更改为不是永久性的(这将是baaaad)。$IFS


答案 2
for i in $LIB/*.jar; do
    CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`