Используя bash, как сделать classpath из всех файлов в каталоге? - PullRequest
61 голосов
/ 19 января 2011

Это будет на самом деле простая халява для гуру Баш:

Вопрос

Используя 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 в форме:

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 ]

110 голосов
/ 19 января 2011

Новый ответ
(октябрь 2012 г.)

Нет необходимости вручную создавать список путей к классам.Java поддерживает удобный подстановочный синтаксис для каталогов, содержащих файлы jar.

java -cp "$LIB/*"

(Обратите внимание, что * это внутри кавычек.)

Пояснение от man java:

В качестве особого удобства элемент пути к классу, содержащий базовое имя *, считается эквивалентным указанию списка всех файлов в каталоге с расширением .jar или .JAR (Java-программа не может определить разницу между этими двумя вызовами).

Например, если каталог foo содержит a.jar и b.JAR, то элемент пути к классу foo/* расширяется до A.jar:b.JAR,за исключением того, что порядок файлов JAR не указан.Все файлы JAR в указанном каталоге, даже скрытые, включены в список.Запись пути к классу, состоящая просто из *, расширяется до списка всех файлов JAR в текущем каталоге.Переменная окружения CLASSPATH, если она определена, будет расширена аналогичным образом.Любое расширение подстановочного знака classpath происходит до запуска виртуальной машины Java - ни одна программа Java никогда не увидит нерасширенные подстановочные знаки, за исключением запросов к среде.


Старый ответ

Хорошо

Простое, но не идеальное решение:

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

Есть небольшой недостаток в том, что это не будет правильно обрабатывать имена файлов с пробелами.Если это имеет значение, попробуйте эту немного более сложную версию:

Лучше

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

Это работает, только если ваша команда поиска поддерживает -printf (как GNU find делает).

Если у вас нет GNU find, как в Mac OS X, вы можете использовать xargs вместо:

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

Best?

Другой (более странный) способсделать это, чтобы изменить переменную разделителя полей $IFS.Это выглядит очень странно, но будет хорошо работать со всеми именами файлов и использовать только встроенные модули оболочки.

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

Объяснение:

  1. JARS установлено в массивимен файлов.
  2. IFS заменен на :.
  3. Массив отображается, а $IFS используется в качестве разделителя между элементами массива.Это означает, что имена файлов печатаются с двоеточиями между ними.

Все это делается в под-оболочке, поэтому изменение на $IFS не является постоянным (что будет baaaad).

8 голосов
/ 19 января 2011
for i in $LIB/*.jar; do
    CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`
2 голосов
/ 19 января 2011

Вот еще одна вариация:

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

printf -v немного похоже на sprintf.Расширение скобки удаляет лишний двоеточие с конца.

0 голосов
/ 19 января 2011

Bestest

Все лучше с awk =)

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