CMD: *. * Ou juste *?

47

Dans les années 1990, j’utilisais " *.*" pour représenter tout nom de fichier dans MS-DOS, mais j’ai vu plus de scripts utiliser simplement " *" ces jours-ci. Cela fait-il réellement une différence que j'utilise?

Foebane
la source
9
Il est vrai que , *et *.*sont maintenant équivalents pour les cmdcommandes internes et utilitaires de ligne de commande modernes, certains utilitaires anciens qui prennent des paramètres de masque de fichier peuvent utiliser les fonctions de comparaison des fichiers anciens, et pour eux les masques ne seront pas équivalents.
AFH
@AFH Je ne pense pas que les jetons sont égaux. Le *.*jeton ne doit pas renvoyer de fichiers sans extension.
Tuskiomi 11/07/17
1
@tuskiomi - Je suis d'accord avec vous pour dire que les fichiers sans extension *.* ne doivent pas être renvoyés . Malheureusement, c'est le cas. Voir la réponse de Grawity.
AFH

Réponses:

65

Le nom de fichier et son extension constituent un champ unique depuis que Windows 95 et NT 3.5 ont introduit la prise en charge du "nom de fichier long", et les correspondances avec des caractères génériques sont effectuées en même temps sur le nom de fichier complet. En conséquence, vous pouvez avoir un nom de fichier sans points (peut-être rare pour les fichiers, mais très commun pour les dossiers / répertoires) et à première vue, *.*il ne correspondrait pas à de tels fichiers.

Anciens scripts à l' aide *.* sera encore du travail à cause du code de compatibilité - si les extrémités génériques avec .*, cette partie est ignorée par le système d' exploitation. (Donc, si vous vouliez faire spécifiquement correspondre les fichiers avec une extension, je suppose que vous en auriez besoin *.?*pour cela.)

Mais ce n'est pas quelque chose sur lequel vous devriez compter; si vous écrivez des scripts pour les versions Windows modernes, suivez leurs conventions, et non celles de MS-DOS. (Notez qu'à partir de Windows NT, les scripts .bat ne sont plus interprétés par MS-DOS mais par cmd.exeun programme Win32 natif.)


Sous Linux et beaucoup d’autres Unixen, nom et extension n’ont jamais été séparés, et il n’ya pas de magie particulière pour faire *.*fonctionner, c’est donc *le seul choix qui a du sens.

Grawity
la source
14
"Faisons en sorte qu'il soit plus difficile de filtrer les fichiers avec des extensions! Yay!" -Développeur Microsoft anonyme
John Hamilton
50
"Brisons les millions de scripts batch existants pour tout le monde! Yay!" -Pas de développeur Microsoft, Jamais
grawity
3
ISTR que sur certaines anciennes versions de DOS, *ne ferait correspondre que les noms de fichiers sans extension. Le moyen "sûr" d'être compatible avec les deux était d'utiliser **.
Random832
8
L'OP concerne Windows, mais puisque vous avez mentionné Linux: Dans certains shells (Bash, par exemple), *ne correspond pas ( par défaut, aux noms de fichiers cachés (en commençant par a .).
Florian Brucker
4
Pour certaines valeurs de "niveau OS" ... C’est aussi un concept de shell (Explorer) dans Windows également - le noyau ne se soucie pas de .exe sur les exécutables, ni de rien d’autre. On peut se demander si Windows Explorer est plus "au niveau du système d'exploitation" que, par exemple, Nautilus sous Linux.
grawity
11

Il est sans doute mentionner la valeur que le unixy / coquilles posixy comme shell bash, ksh, zsh, etc font expansions génériques (des caractères glob aiment *, ?, [range], [!range]et d' autres extensions comme des accolades et globs étendus) pour dresser la liste des arguments avant la commande est exécuté. Donc, cette expansion est faite par le shell et non par la commande à laquelle ils peuvent être des arguments.

c'est-à-dire que le shell est responsable de quoi *, *.*s'étend à

 $ 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

Ce n'est pas le cas dans CMD (et de la même manière pour les utilitaires powershell ) car il transmet les caractères globaux mot pour mot à la commande exécutée - et donc le développement est la responsabilité de la commande / utilitaire et non du shell. En fin de compte, ce *.*ou des *moyens est laissée à l'utilitaire en laissant de se conformer (ou non) aux conventions - ce qui explique pourquoi les utilitaires de CMD aiment dir *.*également les fichiers correspondants (sans doute préserver de manière incorrecte encore aux attentes) sans extensions.

Je crois qu'il est prudent de résumer de cette façon.

  • Sous CMD, cela dépend de l'utilitaire.
  • Sous PowerShell, les utilitaires utilisant la classe WildCardPattern fournissent un sous-ensemble cohérent de comportements posixy.
Shalomb
la source
Une autre différence est que sous CMD, la plupart des programmes transmettent le caractère générique brut au noyau (FindFirstFile), alors que glob sous Linux ne saisit que la liste complète et effectue un filtrage dans l'espace utilisateur.
grawity
Lorsque vous exécutez * sur un répertoire contenant un million de fichiers, la commande se plaint de trop de paramètres. Dans le pire des cas, il pourrait perdre la fin de la liste en silence. Dans ces cas, vous devez diriger deux commandes ou plus, ou enregistrer une liste de noms de fichiers dans un fichier, afin qu'un autre processus puisse lire la liste.
Enric Naval
3
@grawity Pour être plus précis, le filtrage est effectué par le pilote du système de fichiers sous Windows. Ceci est particulièrement utile sur les systèmes de fichiers réseau (en particulier lorsque vous exécutez une ligne de 8 kb sur un système de fichiers distant), mais cela signifie également que vous ne pouvez pas effectuer de recherches arbitraires ni de recherches explicitement prises en charge. Les implications de cela ont été explorées à plusieurs reprises sur le blog de Raymond Chen. FindFirstFilelui-même est en mode utilisateur (kernel32.dll et ntdll.dll sont des bibliothèques en mode utilisateur - cela fait partie du sous-système Win32, pas du noyau), mais cela ne fait pas grand-chose.
Luaan
Ah, j’avais l’impression que FindFirstFile a directement encapsulé un appel système similaire (comme la façon dont open (3) dans la libc enveloppe simplement open (2) dans le noyau Linux).
Grawity
1
@cup: Utilisez simplement des guillemets pour empêcher le shell de développer des globs, vous pourrez ainsi les transmettre à des commandes. par exemple mmv "fred.*" "tom.#1". (Le remplacement utilise #1au lieu de *, ce qui a l’avantage de vous permettre de réorganiser les champs). mmvn'est pas installé par défaut sur la plupart des systèmes, à la différence des autres outils de changement de nom par lot. Voir cet article à ce sujet , et stackoverflow.com/questions/417916/how-to-do-a-mass-rename .
Peter Cordes