Dies wird einreallysimple Freebie für einen bash guru sein:
Frage
Wie macht man mit bash einen Klassenpfad aus allen Dateien in einem Verzeichnis?
Einzelheiten
Gegeben ein Verzeichnis:
LIB=/path/to/project/dir/lib
das enthält nur * .jar-Dateien wie:
junit-4.8.1.jar
jurt-3.2.1.jar
log4j-1.2.16.jar
mockito-all-1.8.5.jar
Ich muss eine durch Doppelpunkt getrennte Klassenpfadvariable im Formular erstellen:
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
Ein Seudo-Code, der die Logik, die ich suche, beinahe ausdrückt, würde ungefähr so aussehen:
for( each file in directory ) {
classpath = classpath + ":" + LIB + file.name
}
Was ist eineinfacherWeg, um dies über das Bash-Skript zu erreichen?
Neue Antwort
(Oktober 2012)
Sie müssen die Klassenpfadliste nicht manuell erstellen. Java unterstützt eine praktische Platzhaltersyntax für Verzeichnisse, die JAR-Dateien enthalten.
Java -cp "$LIB/*"
(Beachten Sie, dass *
inside die Anführungszeichen ist.)
Erklärung von man Java
:
Als besondere Bequemlichkeit gilt ein Klassenpfadelement, das den Basisnamen * enthält, als Äquivalent zur Angabe einer Liste aller Dateien im Verzeichnis mit der Erweiterung
.jar
oder.JAR
(ein Java-Programm kann den Unterschied zwischen den beiden Aufrufen nicht erkennen).Wenn das Verzeichnis foo beispielsweise
a.jar
undb.JAR
enthält, wird das Klassenpfadelementfoo/*
zu einemA.jar:b.JAR
erweitert, mit der Ausnahme, dass die Reihenfolge der JAR-Dateien nicht angegeben ist. Alle JAR-Dateien im angegebenen Verzeichnis, auch versteckte, werden in die Liste aufgenommen. Ein Klassenpfadeintrag, der einfach aus*
besteht, wird zu einer Liste aller JAR-Dateien im aktuellen Verzeichnis erweitert. DieCLASSPATH
-Umgebungsvariable, sofern definiert, wird in ähnlicher Weise erweitert. Jede Erweiterung des Classpath-Platzhalters erfolgt, bevor die Java Virtual Machine gestartet wird. Kein Java-Programm kann einen nicht erweiterten Platzhalter sehen, außer durch Abfragen der Umgebung.
Alte Antwort
Einfache aber nicht perfekte Lösung:
CLASSPATH=$(echo "$LIB"/*.jar | tr ' ' ':')
Es gibt einen kleinen Fehler darin, dass Dateinamen mit Leerzeichen nicht korrekt behandelt werden. Wenn dies wichtig ist, versuchen Sie diese etwas kompliziertere Version:
CLASSPATH=$(find "$LIB" -name '*.jar' -printf '%p:' | sed 's/:$//')
Dies funktioniert nur, wenn Ihr Suchbefehl -printf
(wie GNU find
) unterstützt.
Wenn Sie nicht wie in Mac OS X GNU find
haben, können Sie stattdessen xargs
verwenden:
CLASSPATH=$(find "." -name '*.jar' | xargs echo | tr ' ' ':')
Eine andere (seltsamere) Möglichkeit besteht darin, die Feldtrennungsvariable $IFS
zu ändern. Dies sieht sehr seltsam aus, verhält sich jedoch bei allen Dateinamen gut und verwendet nur integrierte Shell-Programme.
CLASSPATH=$(JARS=("$LIB"/*.jar); IFS=:; echo "${JARS[*]}")
Erläuterung:
JARS
ist auf ein Array von Dateinamen gesetzt.IFS
wird in :
geändert.$IFS
wird als Trennzeichen zwischen den Arrayeinträgen verwendet. Die Dateinamen werden also mit Doppelpunkten zwischen den Dateinamen gedruckt.All dies geschieht in einer Sub-Shell, so dass die Änderung zu $IFS
nicht dauerhaft ist (was baaaad wäre).
for i in $LIB/*.jar; do
CLASSPATH=$CLASSPATH:$i
done
CLASSPATH=`echo $CLASSPATH | cut -c2-`
Hier ist eine andere Variante:
printf -v CLASSPATH "$LIB/%s:" *.jar; CLASSPATH=${CLASSPATH%:}
printf -v
ist etwas wie sprintf
. Die Klammererweiterung entfernt den zusätzlichen Doppelpunkt am Ende.
Alles ist besser mit awk
=)
CLASSPATH=$(awk '$0=lib"/"FILENAME' ORS=":" lib=$LIB *.jar)