Es wird versucht, alle Dateien aus dem aktuellen Verzeichnis zum Archiv hinzuzufügen und die Ausgabedatei entsprechend einem bestimmten hinzugefügten Dateinamen/einer bestimmten Dateierweiterung zu benennen.
Wenn eine Datei mit der Erweiterung .exe hinzugefügt wird, soll der Archivname grundsätzlich mit dem der Datei identisch sein, vorausgesetzt, es gibt nur eine und mindestens eine .exe.
Foo.exe -> Foo.7z
Hier ist das Skript, das ich bisher habe 7z a archive.7z *.* -x!*.sh
Antwort1
set -- *.exe
speichert übereinstimmende Dateinamen *.exe
als Positionsparameter, es sei denn, es gibt keine Übereinstimmung. Falls keine Übereinstimmung vorliegt, hängt das Ergebnis von der Shell ab (siehe den Anfang vondiese Antwort); in der POSIX-Shell erhalten Sie die Literalzeichenfolge *.exe
als ersten und einzigen Positionsparameter.
Wenn Sie sicher sind, dass es genau eine Übereinstimmung gibt, müssen Sie nichts testen. Wenn Sie sich nicht sicher sind, dann:
- prüfen, ob
$#
es sich zu1
([ "$#" -eq 1 ]
) erweitert, - prüfen, ob die angebliche Datei existiert (
[ -e "$1"]
).
Dann ist der Name, nach dem Sie suchen, in $1
. Um zu übersetzen, Foo.exe
müssen Foo.7z
Sieentfernenexe
und fügen Sie 7z
( ${1%exe}7z
) hinzu.
Der Snippet sieht etwa so aus:
(
set -- *.exe
# here validate $# and/or $1 if necessary
7z a "${1%exe}7z" …
)
Ich habe eine Untershell verwendet, daher set
werden die Positionsparameter der Hauptshell nicht beeinflusst.Zitieren ist wichtig.
Anmerkungen:
- Die Lösung ermöglicht es, dass die Übereinstimmung ein Verzeichnis ist.Jedes Verzeichnis ist auch eine Datei.
- Sie haben „alle Dateien hinzufügen“ geschrieben und dann verwendet
*.* -x!*.sh
. Ich werde nicht kleinlich sein und sagen, dass der Ausschluss „alle Dateien“ widerspricht. Es gibt jedoch Probleme:-x!*.sh
sollte in Anführungszeichen stehen, damit die Shell niemals erweitert wird*
. Die Zeichenfolge sollte in einfache Anführungszeichen gesetzt werden, da einige Shells!
sogar in doppelten Anführungszeichen erweitert werden.*.*
kann in Windows "alle Dateien" bedeuten (zumindestmit einigen Werkzeugen), aber in einer Linux-Shell entspricht der Punkt strikt einem Punkt.*
als Muster zur Generierung von Dateinamen ist näher an "alle Dateien",immer noch nicht "alle Dateien".
- Die Lösung ist anfällig fürTOCTOU. Wahrscheinlich ändert sich der Inhalt Ihres Verzeichnisses nicht „zufällig“ und die Lösung wird funktionieren. Wenn das Verzeichnis nicht statisch ist, muss man möglicherweise ein Archiv mit temporärem Namen erstellen, seinen Inhalt auflisten und analysieren, um herauszufinden, was
.exe
(falls überhaupt) in das Archiv gelangt ist, und das Archiv schließlich entsprechend umbenennen. - Beachten Sie, dass Dateinamen in Linux im Allgemeinen zwischen Groß- und Kleinschreibung unterscheiden. Tools, die mit Dateinamen arbeiten, tun dies ebenfalls. Normalerweise
set -- *.exe
erkennt nichtFOO.EXE
. In einigen Shells können Sie dieses Verhalten anpassen (z. B. investigateshopt -s nocaseglob
in Bash); dann sollten Sie verwenden, um bei der Namensübersetzung${1%[eE][xX][eE]}7z
richtig mitEXE
, oder einer anderen Variante umzugehen.Exe