CMD: *. * Oder nur *?

47

In den 90er Jahren habe ich *.*jeden Dateinamen in MS-DOS " " dargestellt, aber ich habe in *diesen Tagen mehr Skripte gesehen, die nur " " verwendet haben. Macht es überhaupt einen Unterschied, welches ich benutze?

Foebane
quelle
9
Zwar sind *und *.*bleiben cmdinterne Befehle und moderne Befehlszeilendienstprogramme gleich, doch einige ältere Dienstprogramme, die Dateimaskenparameter verwenden, verwenden möglicherweise ältere Funktionen zum Abgleichen von Dateien. Für sie sind die Masken jedoch nicht gleichwertig.
AFH
@AFH Ich glaube nicht, dass die Token gleich sind. Das *.*Token sollte keine Dateien ohne Erweiterung zurückgeben.
Tuskiomi
1
@tuskiomi - Ich würde Ihnen zustimmen, dass *.* keine erweiterungslosen Dateien zurückgegeben werden sollten. Leider schon. Siehe Grawitys Antwort.
AFH

Antworten:

65

Dateiname und Dateierweiterung waren ein einziges Feld , seit Windows 95 und NT 3.5 die Unterstützung für lange Dateinamen einführten. Wildcard-Übereinstimmungen werden für den gesamten Dateinamen auf einmal durchgeführt. Infolgedessen können Sie einen Dateinamen ohne Punkte haben (möglicherweise selten für Dateien, aber sehr häufig für Ordner / Verzeichnisse), und auf den ersten Blick *.*stimmen solche Dateien nicht wirklich überein.

Alte Skripte *.* werden nach wie vor Arbeit wegen Kompatibilitätscode - wenn die Platzhalter Enden mit .*, dass ein Teil wird durch das OS ignoriert. (Wenn Sie also Dateien mit einer bestimmten Dateierweiterung zuordnen möchten, brauchen Sie das wahrscheinlich *.?*.)

Aber darauf sollten Sie sich nicht verlassen. Wenn Sie Skripte für moderne Windows-Versionen schreiben, befolgen Sie deren Konventionen, nicht MS-DOS-Konventionen. (Beachten Sie, dass ab Windows NT .bat-Skripte nicht mehr von MS-DOS, sondern von cmd.exeeinem systemeigenen Win32-Programm interpretiert werden .)


Unter Linux und verschiedenen anderen Unixen waren Name und Erweiterung noch nie voneinander getrennt, und es gibt keine besondere Magie, mit der man *.*arbeiten könnte. Es ist also *die einzige Wahl, die Sinn macht.

Grawity
quelle
14
"Machen wir es uns schwerer, Dateien mit Erweiterungen zu filtern! Yay!" -Anonymer Microsoft-Entwickler
John Hamilton
50
"Lassen Sie uns die Millionen existierender Batch-Skripte für alle brechen! Yay!" -Keine Microsoft Developer, Ever
Grawity
3
ISTR, dass auf einigen alten DOS-Versionen *nur Dateinamen ohne Erweiterung übereinstimmen würden . Die "sichere" Möglichkeit, mit beiden kompatibel zu sein, war die Verwendung **.
Random832
8
Das OP handelt von Windows, aber da Sie Linux erwähnt haben: In einigen Shells (z. B. Bash ) stimmen *( standardmäßig ) versteckte Dateinamen nicht überein (beginnend mit a .).
Florian Brucker
4
Für einige Werte der "Betriebssystemebene" ... Es ist auch ein Shell (Explorer) -Konzept in Windows - der Kernel kümmert sich weder um .exe auf ausführbaren Dateien noch um irgendetwas anderes. Ob der Windows Explorer mehr "OS-Level" hat als zB Nautilus unter Linux, kann diskutiert werden.
Grawity
11

Es ist wahrscheinlich erwähnenswert , dass die Unixy / posixy Schalen wie die Bourne - Shell bash, ksh, zsh usw. Wildcard Erweiterung zu tun (von glob Zeichen wie *, ?, [range], [!range]und andere Erweiterungen wie Klammern und erweitern Klackse) eine Liste von Argumenten zu kompilieren , bevor der Befehl ausgeführt wird. Diese Erweiterung erfolgt also durch die Shell und nicht durch den Befehl, für den dies möglicherweise ein Argument ist.

dh die Shell ist dafür verantwortlich, was *sich *.*ausdehnt

 $ ls
 file.csv  file.doc  file.pdf  file.txt  file.xlsx  zz-file-without-extension

 $ (set -xv; foo *)   # is actually expanded to the following
   + foo file.csv file.doc file.pdf file.txt file.xlsx zz-file-without-extension

 $ (set -xv; foo *.*)  # note this does not match `zz-file-without-extension`
   + foo file.csv file.doc file.pdf file.txt file.xlsx

Dies ist in CMD nicht der Fall (und dies gilt auch für Powershell-Dienstprogramme ), da die Glob-Zeichen wörtlich an den ausgeführten Befehl übergeben werden. Daher liegt die Erweiterung in der Verantwortung des Befehls / Dienstprogramms und nicht der Shell. Letztendlich bleibt es dem Dienstprogramm überlassen , was *.*oder was es *bedeutet, Konventionen einzuhalten (oder nicht). Aus diesem Grund dir *.*passen die Dienstprogramme von CMD auch Dateien ohne Erweiterungen an (vermutlich fälschlicherweise, jedoch unter Beibehaltung der Erwartungen).

Ich glaube, es ist sicher, diesen Weg zusammenzufassen.

  • Unter CMD hängt es vom Dienstprogramm ab.
  • Unter PowerShell stellen Dienstprogramme, die die WildCardPattern-Klasse verwenden , eine konsistente Untermenge von Posixy-Verhalten bereit.
shalomb
quelle
Ein weiterer Unterschied besteht darin, dass unter CMD die meisten Programme den unformatierten Platzhalter tatsächlich an den Kernel (FindFirstFile) weiterleiten, während glob unter Linux nur die vollständige Liste erfasst und im Benutzerbereich filtert.
Grawity
Wenn Sie * in einem Verzeichnis mit einer Million Dateien ausführen, beschwert sich der Befehl über zu viele Parameter. Im schlimmsten Fall könnte es stillschweigend den Schluss der Liste fallen lassen. In diesen Fällen müssen Sie zwei oder mehr Befehle übergeben oder eine Liste mit Dateinamen in einer Datei speichern, damit andere Prozesse die Liste lesen können.
Enric Naval
3
@grawity Um genauer zu sein, wird die Filterung vom Dateisystemtreiber unter Windows durchgeführt. Dies ist besonders nützlich in Netzwerk-Dateisystemen (insbesondere dann, wenn Sie eine 8-KB-Leitung zu einem Remote-Dateisystem verwenden könnten), aber es bedeutet auch, dass Sie keine willkürlichen Suchvorgänge sowie explizit unterstützte Suchvorgänge ausführen können. Die Implikationen davon wurden viele Male in Raymond Chens Blog untersucht. FindFirstFileselbst ist der Benutzermodus (sowohl kernel32.dll als auch ntdll.dll sind Benutzermodus-Bibliotheken - es ist Teil des Win32-Subsystems, nicht des Kernels), aber es macht nicht wirklich viel.
Luaan
Ah, ich hatte den Eindruck, dass FindFirstFile einen ähnlich benannten syscall so ziemlich direkt umschlossen hat (so wie open (3) in libc nur open (2) im Linux-Kernel).
Grawity
1
@cup: Verwenden Sie einfach Anführungszeichen, um zu verhindern, dass die Shell Globs erweitert, damit Sie sie an Befehle übergeben können. zb mmv "fred.*" "tom.#1". (Der Ersatz verwendet #1anstelle von *, was den Vorteil hat, dass Sie Felder nachbestellen können). mmvwird auf den meisten Systemen nicht standardmäßig installiert, andere Tools zum Batch-Umbenennen jedoch häufig. Lesen Sie diesen Artikel und stackoverflow.com/questions/417916/how-to-do-a-mass-rename .
Peter Cordes