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

发布于 2024-10-13 03:44:10 字数 798 浏览 3 评论 0原文

对于 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

一些几乎表达了我正在查找的逻辑的伪代码for 的思路是:

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

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

This will be a really simple freebie for a bash guru:

Question

Using bash, how do you make a classpath out of all files in a directory?


Details

Given a directory:

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

that contains nothing but *.jar files such as:

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

I need to create a colon-separated classpath variable in the form:

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

Some seudo-code that nearly expresses the logic I'm looking for would be along the lines of:

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

What is a simple way to accomplish this via bash script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

那小子欠揍 2024-10-20 03:44:10

新答案
(2012 年 10 月)

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

java -cp "$LIB/*"

(请注意,* 位于引号内部。)

来自 man java 的解释:

为了方便起见,包含基名 * 的类路径元素被认为等效于指定目录中扩展名为 .jar.JAR< 的所有文件的列表。 /code> (java 程序无法区分两次调用之间的区别)。

例如,如果目录 foo 包含 a.jarb.JAR,则类路径元素 foo/* 会扩展为a 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 用作数组条目之间的分隔符。这意味着文件名之间用冒号打印。

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

New Answer
(October 2012)

There's no need to manually build the classpath list. Java supports a convenient wildcard syntax for directories containing jar files.

java -cp "$LIB/*"

(Notice that the * is inside the quotes.)

Explanation from man java:

As a special convenience, a class path element containing a basename of * is considered equivalent to specifying a list of all the files in the directory with the extension .jar or .JAR (a java program cannot tell the difference between the two invocations).

For example, if directory foo contains a.jar and b.JAR, then the class path element foo/* is expanded to a A.jar:b.JAR, except that the order of jar files is unspecified. All jar files in the specified directory, even hidden ones, are included in the list. A classpath entry consisting simply of * expands to a list of all the jar files in the current directory. The CLASSPATH environment variable, where defined, will be similarly expanded. Any classpath wildcard expansion occurs before the Java virtual machine is started — no Java program will ever see unexpanded wildcards except by querying the environment.


Old Answer

Good

Simple but not perfect solution:

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

There's a slight flaw in that this will not handle file names with spaces correctly. If that matters try this slightly more complicated version:

Better

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

This only works if your find command supports -printf (as GNU find does).

If you don't have GNU find, as on Mac OS X, you can use xargs instead:

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

Best?

Another (weirder) way to do it is to change the field separator variable $IFS. This is very strange-looking but will behave well with all file names and uses only shell built-ins.

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

Explanation:

  1. JARS is set to an array of file names.
  2. IFS is changed to :.
  3. The array is echoed, and $IFS is used as the separator between array entries. Meaning the file names are printed with colons between them.

All of this is done in a sub-shell so the change to $IFS isn't permanent (which would be baaaad).

浊酒尽余欢 2024-10-20 03:44:10
for i in $LIB/*.jar; do
    CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`
for i in $LIB/*.jar; do
    CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`
比忠 2024-10-20 03:44:10

这是另一种变体:

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

printf -v 有点像sprintf。大括号扩展从末尾删除了多余的冒号。

Here's another variation:

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

printf -v is somewhat like sprintf. The brace expansion removes the extra colon from the end.

伴梦长久 2024-10-20 03:44:10

最好的

一切都比awk更好 =)

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

Bestest

Everything is better with awk =)

CLASSPATH=$(awk '$0=lib"/"FILENAME' ORS=":" lib=$LIB *.jar)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文