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

gMa*_*ale 62 java directory bash file classpath

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

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


细节

给定一个目录:

LIB=/path/to/project/dir/lib
Run Code Online (Sandbox Code Playgroud)

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

junit-4.8.1.jar
jurt-3.2.1.jar
log4j-1.2.16.jar
mockito-all-1.8.5.jar
Run Code Online (Sandbox Code Playgroud)

我需要在表单中创建一个冒号分隔的classpath变量:

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
Run Code Online (Sandbox Code Playgroud)

一些几乎表达我正在寻找的逻辑的seudo代码将遵循:

for( each file in directory ) {
   classpath = classpath + ":" + LIB + file.name
}
Run Code Online (Sandbox Code Playgroud)

通过bash脚本实现此目的的简单方法是什么?

Joh*_*ica 112

新答案
(2012年10月)

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

java -cp "$LIB/*"
Run Code Online (Sandbox Code Playgroud)

(请注意,*引号内.)

解释来自man java:

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

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


老答案

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

CLASSPATH=$(echo "$LIB"/*.jar | tr ' ' ':')
Run Code Online (Sandbox Code Playgroud)

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

更好

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

这仅在您的find命令支持时有效-printf(如GNU find那样).

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

CLASSPATH=$(find "." -name '*.jar' | xargs echo | tr ' ' ':')
Run Code Online (Sandbox Code Playgroud)

最好?

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

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

说明:

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

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


biz*_*lop 8

for i in $LIB/*.jar; do
    CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的答复.我剪切/粘贴它,它运行得很好.这是使用for循环来完成这样的事情的一个很好的例子. (2认同)