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

时间:2011-01-18 22:36:46

标签: java bash file directory classpath

对于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脚本实现此目的的 简单 方式是什么?

4 个答案:

答案 0 :(得分:110)

新答案
(2012年10月)

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

java -cp "$LIB/*"

(请注意,* 里面是引号。)

来自man java的说明:

  

作为一种特殊的方便,包含基本名称*的类路径元素被认为等同于指定扩展名为.jar.JAR的目录中的所有文件的列表(java程序不能告诉两次调用之间的区别。)

     

例如,如果目录foo包含a.jarb.JAR,则类路径元素foo/*将扩展为A.jar:b.JAR,但jar文件的顺序为不确定的。指定目录中的所有jar文件,甚至是隐藏的文件都包含在列表中。简单地由*组成的类路径条目扩展为当前目录中所有jar文件的列表。定义的CLASSPATH环境变量将同样进行扩展。任何类路径通配符扩展都在Java虚拟机启动之前发生 - 除了查询环境之外,任何Java程序都不会看到未展开的通配符。


旧答案

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

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

存在一个轻微的缺陷,即它无法正确处理带空格的文件名。如果重要的是尝试这个稍微复杂的版本:

更好

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

仅当您的find命令支持-printf时(如GNU find那样),此方法才有效。

如果您没有GNU find,就像在Mac OS X上一样,您可以改为使用xargs

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

最佳?

另一种(更奇怪的)方法是更改​​字段分隔符变量$IFS。这看起来非常奇怪,但对所有文件名都表现良好,只使用shell内置函数。

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

说明:

  1. JARS设置为文件名数组。
  2. IFS已更改为:
  3. 回显数组,$IFS用作数组条目之间的分隔符。这意味着文件名在它们之间用冒号打印。
  4. 所有这些都是在子shell中完成的,因此对$IFS的更改不是永久性的(这将是baaaad)。

答案 1 :(得分:8)

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

答案 2 :(得分:2)

这是另一种变体:

printf -v CLASSPATH "$LIB/%s:" *.jar; CLASSPATH=${CLASSPATH%:}

printf -v有点像sprintf。支架扩展从末端移除了额外的冒号。

答案 3 :(得分:0)

BESTEST

使用awk =)

一切更好

CLASSPATH=$(awk '$0=lib"/"FILENAME' ORS=":" lib=$LIB *.jar)