Подтвердить что ты не робот

Используя bash, как вы создаете путь к классам из всех файлов в каталоге?

Это будет действительно простая халява для гуру 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, разделенную двоеточием, в форме:

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 script?

4b9b3361

Ответ 1

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

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

java -cp "$LIB/*"

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

Объяснение из man java:

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

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

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

Пояснение:

  • JARS устанавливается в массив имен файлов.
  • IFS изменен на :.
  • Массив эхом, а $IFS используется как разделитель между элементами массива. Значение имена файлов печатаются с двоеточиями между ними.

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

Ответ 2

for i in $LIB/*.jar; do
    CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`

Ответ 3

Здесь другая вариация:

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

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

Ответ 4

Bestest

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

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