对于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脚本实现此目的的 简单 方式是什么?
答案 0 :(得分:110)
新答案
(2012年10月)
无需手动构建类路径列表。 Java支持包含jar文件的目录的方便的通配符语法。
java -cp "$LIB/*"
(请注意,*
里面是引号。)
来自man java
的说明:
作为一种特殊的方便,包含基本名称*的类路径元素被认为等同于指定扩展名为
.jar
或.JAR
的目录中的所有文件的列表(java程序不能告诉两次调用之间的区别。)例如,如果目录foo包含
a.jar
和b.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[*]}")
说明:
JARS
设置为文件名数组。IFS
已更改为:
。$IFS
用作数组条目之间的分隔符。这意味着文件名在它们之间用冒号打印。所有这些都是在子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)
awk
=) 一切更好
CLASSPATH=$(awk '$0=lib"/"FILENAME' ORS=":" lib=$LIB *.jar)