it-swarm.com.de

Wie macht man mit bash einen Klassenpfad aus allen Dateien in einem Verzeichnis?

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?

60
gMale

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 und b.JAR enthält, wird das Klassenpfadelement foo/* zu einem A.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. Die CLASSPATH-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

Gut

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:

Besser

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 ' ' ':')

Beste?

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:

  1. JARS ist auf ein Array von Dateinamen gesetzt.
  2. IFS wird in : geändert.
  3. Das Array wird bestätigt und $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).

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

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.

2

Bestest

Alles ist besser mit awk =)

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