Java 使用bash,如何从目录中的所有文件中生成类路径?
对于bash大师来说,这将是一个非常简单的免费赠品: 问题 使用bash,如何从目录中的所有文件中生成类路径Java 使用bash,如何从目录中的所有文件中生成类路径?,java,bash,file,directory,classpath,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
详细信息 给定目录:
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脚本实现这一点的简单方法是什么?新答案 (2012年10月) 不需要手动构建类路径列表。Java支持对包含jar文件的目录使用方便的通配符语法
java -cp "$LIB/*"
(请注意,*
位于引号内。)
man java的解释:
为方便起见,包含basename*的类路径元素被认为等同于指定目录中所有文件的列表,扩展名为.jar
或.jar
(java程序无法区分这两个调用之间的差异)
例如,如果目录foo包含a.jar
和b.jar
,则类路径元素foo/*
将扩展为aa.jar:b.jar
,但jar文件的顺序未指定。列表中包括指定目录中的所有jar文件,甚至是隐藏的文件。仅由*
组成的类路径项扩展为当前目录中所有jar文件的列表。CLASSPATH
环境变量(在定义的地方)将类似地展开。任何类路径通配符扩展都发生在Java虚拟机启动之前-任何Java程序都不会看到未扩展的通配符,除非通过查询环境
旧答案 好 简单但不完美的解决方案:
CLASSPATH=$(echo "$LIB"/*.jar | tr ' ' ':')
有一个轻微的缺陷,这将无法正确处理带有空格的文件名。如果这很重要,请尝试这个稍微复杂一点的版本:
更好
这仅在find命令支持-printf
(与GNUfind
一样)时才有效
如果在Mac OS X上没有GNUfind
,则可以使用xargs
:
CLASSPATH=$(find "." -name '*.jar' | xargs echo | tr ' ' ':')
最好的?
另一种(更奇怪的)方法是更改字段分隔符变量$IFS
。这看起来很奇怪,但在所有文件名中都表现良好,并且只使用shell内置
CLASSPATH=$(JARS=("$LIB"/*.jar); IFS=:; echo "${JARS[*]}")
说明:
JARS
设置为文件名数组IFS
更改为:
$IFS
用作数组项之间的分隔符。这意味着文件名之间用冒号打印$IFS
的更改不是永久性的(这将是baaad);做
CLASSPATH=$CLASSPATH:$i
完成
CLASSPATH=`echo$CLASSPATH | cut-c2-`
Best
有了awk,一切都变得更好了
这是另一种变化:
printf -v CLASSPATH "$LIB/%s:" *.jar; CLASSPATH=${CLASSPATH%:}
printf-v
有点像sprintf
。大括号扩展将从末尾删除额外的冒号。需要是printf-v类路径“$LIB/%s”*.jar
。对尾随冒号的调用很好,我必须查找它,看看它是否有区别,显然它有区别,它是一个有效的NUL目录,导致搜索当前目录(这可能是可取的,也可能是不可取的)。@SeigeX:我做了你建议的更改。我最初的回答是基于“目录中的所有文件”和问题中的“只包含*.jar文件”,但有选择性是值得的。谢谢你的回答。当我剪切/粘贴并运行它时,我得到一个由空格而不是冒号分隔的类路径。我不知道为什么。除此之外,它工作得很好。@gmale:我无法复制它。检查IFS
是否有默认值以外的值(空格选项卡换行符),但这不应影响此值。如果执行printf“%s:\n”*.jar
操作,是否看到任何空格?那printf'[%s]\n'$LIB'呢?谢谢您花时间回答。我剪切/粘贴了它,它生成了错误awk:cannotopenfile*.jar
。因此,我删除了*.jar(因为所有文件都是lib目录中的jar),脚本挂起,就像等待输入一样。我尝试了其他一些调整,但我对awk的了解还不够,无法修复它。谢谢您的回复。这个简单的版本非常好用。对我来说,更好的解决方案失败了,因为printf不是find命令的有效选项(可能我需要在这台机器上使用3.2.48更新bash?)。最好的选择非常有效。当然,“good”和“best”选项都不能避开文件名中的空格,这对我来说很好,因为没有空格。@gmale-如果在使用CLASSPATH时也引用它,那么更好和最好的选项将容纳空格,如在java-cp“$CLASSPATH”
中,“best”确实是最好的。“更好”的方法不会用空格处理jar文件名。我认为最常用的解决方案是CLASSPATH=$(查找“$LIB”-name'*.jar'| paste-sd:-)
。那么您就不需要这种“奇怪的”数组bashism或GNUfind
。(我在这里使用一个显式的-
输入参数,使它也适用于BSD粘贴
)如果您不想设置类路径
,如果$LIB
目录不包含JAR,您可以先运行shopt-s nullglob
。感谢您的回复。我剪切/粘贴了这个,它运行得非常好。这是一个很好的例子,使用for循环来完成类似的事情。-c2-
参数to cut做什么?我想可能是-c2-
挤压在一起,但结果不同。如果我完全忽略了切割,我会得到相同的结果。这是干什么用的?这是一个很好的答案
CLASSPATH=$(awk '$0=lib"/"FILENAME' ORS=":" lib=$LIB *.jar)
printf -v CLASSPATH "$LIB/%s:" *.jar; CLASSPATH=${CLASSPATH%:}