Pourquoi `dir *. *` Me donne-t-il tous les fichiers et dossiers?

62

Quand je cours, dir *.*cela produit des résultats inattendus. Même les fichiers et les dossiers sans nom dans leur nom sont répertoriés. Par exemple

C:\>dir *.*
 Volume in drive C is System
 Volume Serial Number is AC0A-29DA

 Directory of C:\

14-03-2017  05:17 PM             8,192 ntuser.dat
03-01-2017  07:10 PM    <DIR>          Perl520
28-03-2017  10:13 AM    <DIR>          Program Files
28-03-2017  10:13 AM    <DIR>          Program Files (x86)
04-01-2017  03:25 PM    <JUNCTION>     Python27 [C:\Program Files\Anaconda]
06-02-2017  10:16 PM    <DIR>          SAP
28-03-2017  04:10 PM               152 useragent.log
03-01-2017  03:04 PM    <DIR>          Users
16-03-2017  04:24 PM    <DIR>          VM
22-03-2017  11:13 AM    <DIR>          Windows
               2 File(s)          8,344 bytes
               8 Dir(s)  270,172,966,912 bytes free

Pourquoi donc? Est-il possible de ne lister que les fichiers avec un point?

phuclv
la source
19
Le point est toujours présent, il n’est simplement pas imprimé à moins que quelque chose ne le suive. En d'autres termes, vous pourriez penser qu'un fichier s'appelle "ceci est mon fichier" mais secrètement le nom est "ceci est mon fichier". avec rien après le point. De façon analogue, vous pourriez penser que le nom DNS de ce site est "superutilisateur.com", mais qu’il s’agit en fait de "superutilisateur.com". avec rien après le deuxième point.
Todd Wilcox
12
@ ToddWilcox n'est correct que sous DOS. Les systèmes de fichiers modernes de Windows ne disposent plus d'un espace de noms d'extension distinct
phuclv
13
@ LưuVĩnhPhúc Le sous-système Win32 traite les noms de fichiers qui ne contiennent pas un .comme ils le sont .à la fin pour plusieurs raisons, y compris celle-ci.
CodesInChaos
2
Les dossiers qui ne contiennent pas le .caractère ont un .caractère implicite à la fin. - Vous pouvez par exemple avoir un dossier nommé "Blah.old", qui aura alors une extension de fichier classique de 3 lettres; pour une utilisation quotidienne bien que " Blah" soit identique à " Blah.", qu'il s'agisse d'un fichier ou d'un dossier.
BrainSlugs83
9
@ can-ned_food Todd Wilcox a raison sur le DNS. La zone DNS racine est appelée littéralement ., et les étiquettes des noms DNS sont séparées par .(le nom de la zone DNS racine est donc une étiquette de longueur nulle). Un enfant de la zone DNS racine .est com.et un enfant de com.est superuser.com., et ainsi de suite.
un CVn

Réponses:

115

J'écris cette réponse parce que OP a souligné que:

ce qui m'intéresse, c'est pourquoi *.*correspond à tous les fichiers, comme indiqué dans la question

La DIRcommande vient d'un moment où:

  1. Le point (.) N'était pas autorisé en tant que caractère dans les noms de fichiers ou de dossiers
  2. Les noms de fichiers et de dossiers étaient limités à 8 caractères pour le nom et à 3 caractères pour les extensions.

Par conséquent, par cette norme, on *.*entend quel que soit le nom et quelle que soit l’extension . Cela ne signifie pas une chaîne contenant un ".", Qui peut ou non avoir des caractères avant ou après le "." .

La politique de Microsoft préserve la compatibilité ascendante. Par conséquent, cette interprétation de *.*est retenue.

Mais dans Windows PowerShell, *.*signifie une chaîne contenant un ".", Qui peut ou non comporter des caractères avant ou après le "." .

jpaugh
la source
10
Lectures
grawity Le
25
Le système de fichiers d'origine ne stockait même pas la période sur le disque, seuls les 11 caractères composant le reste du nom.
M. Lister
7
Il est à noter que les fichiers et les dossiers sans extension sont toujours traités comme ayant une extension vierge . Par conséquent, un dossier nommé " Folder." et un dossier nommé " Folder" portent le même nom en ce qui concerne Windows.
BrainSlugs83
2
@ M. Lister Intéressant. Comment les anciens fichiers de magasin FS ont-ils ressemblé AA.BBavec <8 dans la première partie et <3 dans l'extension? A-t-il simplement rempli d'espaces?
Kelvin
3
@ Kelvin oui, les deux parties étaient séparées par un espace séparé.
plugwash
12

Pourquoi donc?

On pourrait trouver une réponse à " Pourquoi est-ce? " Dans l' article Wildcards :

The * wildcard will match any sequence of characters
               (0 or more, including NULL characters)

The ? wildcard will match a single character
               (or a NULL at the end of a filename)

Règles de correspondance générique

  • *Correspond généralement à 0 caractère ou plus, à une exception près (voir la règle suivante). Le caractère générique non gourmand est libre de faire correspondre le nombre de caractères nécessaire pour que le reste du masque corresponde.

  • *.À la fin du masque, correspond à tout caractère égal ou supérieur à 0, à l'exception de {point}. En réalité, la règle s'applique avec un nombre quelconque de caractères {point} et {espace} entre le * et le terminal {point}. L’expression régulière de ce terme est"[*][. ]*[.]$"

  • ?Match 0 ou un caractère, sauf pour {dot}. La seule fois où il correspond à 0 caractère, c'est quand il correspond à la fin du nom ou à la position avant un {point}. Le point d'interrogation peut également être utilisé plusieurs fois pour faire correspondre plusieurs caractères.

Implication . Le dernier {point} d'un nom de fichier / dossier sépare le nom de base et l'extension. Alors

  • dir *.affiche tous les articles sans extension , et
  • dir *.*affiche tous les éléments avec une extension de zéro ou plusieurs caractères .

À proprement parler, dir *.affiche tous les éléments sans. nom ( ) . (Article BTW, noms de fichiers, chemins d'accès et espaces de noms, article MSDN stipulant explicitement qu '" il est acceptable de spécifier un point comme premier caractère d'un nom ".)

Est-il possible de ne lister que les fichiers avec un point?

Je ne pense pas. Toutefois, il existe une solution de contournement avec une expression régulière appropriée.

PowerShell (solution complète si utilisée dans une console Powershell):

:: PowerShell - no extension, full syntax
PowerShell -c "Get-ChildItem | Where-Object {$_.Name -match '^.[^\.]*$'}"
:: PowerShell -    extension, alias syntax
PowerShell -c "dir | ? {$_.Name -match '^..*\...*$'}"

Cmd (une idée seulement, peut nécessiter quelques précisions):

:: CMD/batch - no extension
for /F "delims=" %%G in ('dir /OGN /B ^| findstr "^.[^\.]*$"') do @echo %%~tG %%~aG %%~zG %%~nxG
:: CMD/batch -    extension
for /F "delims=" %%G in ('dir /OGN /B ^| findstr "^..*\...*$"') do @echo %%~tG %%~aG %%~zG %%~nxG

Addendum: un bonus et une explication

Une hypothèse intuitive qui Nameest concaténée BaseNameet Extension ne tient pas . Le script suivant prouve à l'aide cmdet PowerShellfonctionnalités de base, et l' étrange ^..*\...*$ regex est dérivé de résultats est tout.

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "_workingDirectory=%~1"
if "%_workingDirectory%"=="%tmp%\tests_SU_1193102" (
  >NUL 2>&1 (
      mkdir "%_workingDirectory%"
      pushd "%_workingDirectory%"
      rem make directories
      mkdir     .Fldr-Ext
      mkdir     aFldr-Ext
      mkdir     .Fldr.Ext
      mkdir     aFldr.Ext
      rem create files
      copy  NUL .File-Ext 
      copy  NUL aFile-Ext 
      copy  NUL .File.Ext 
      copy  NUL aFile.Ext
      popd
  )
) else if "%_workingDirectory%"=="" set "_workingDirectory=%CD%"
pushd "%_workingDirectory%"
set "_first=ItemName  Attributes    BaseName Extension"
echo ON
::                        dir /OGN | findstr "Ext$"
for /F "delims=" %%G in ('dir /OGN /B') do @((if defined _first (echo %_first%&echo(&set "_first="))&echo %%~nxG %%~aG  %%~nG   %%~xG)
::   Get-ChildItem | Select-Object -Property Mode, BaseName, Extension, Name
PowerShell -c "dir | select -pr Name, Mode, BaseName, Extension | sort -pr @{Expression='Mode';Descending=$true}, @{Expression='Name';Descending=$false}"

Sortie :

==> D:\bat\BaseName_vs_Extension.bat "%tmp%\tests_SU_1193102"

==> for /F "delims=" %G in ('dir /OGN /B') do @((if defined _first (echo ItemName  Attributes   BaseName Extension  & echo(  & set "_first=" ) )  & echo %~nxG %~aG     %~nG    %~xG )
ItemName  Attributes    BaseName Extension

.Fldr.Ext d----------   .Fldr   .Ext
.Fldr-Ext d----------           .Fldr-Ext
aFldr.Ext d----------   aFldr   .Ext
aFldr-Ext d----------   aFldr-Ext
.File.Ext --a--------   .File   .Ext
.File-Ext --a--------           .File-Ext
aFile.Ext --a--------   aFile   .Ext
aFile-Ext --a--------   aFile-Ext

==> PowerShell -c "dir | select -pr Name, Mode, BaseName, Extension | sort -pr @{Expression='Mode';Descending=$true}, @{Expression='Name';Descending=$false}"

Name      Mode   BaseName  Extension
----      ----   --------  ---------
.Fldr.Ext d----- .Fldr.Ext .Ext
.Fldr-Ext d----- .Fldr-Ext .Fldr-Ext
aFldr.Ext d----- aFldr.Ext .Ext
aFldr-Ext d----- aFldr-Ext
.File.Ext -a---- .File     .Ext
.File-Ext -a----           .File-Ext
aFile.Ext -a---- aFile     .Ext
aFile-Ext -a---- aFile-Ext

Comparez la définition de la BaseNamepropriété, différente pour les fichiers et les dossiers:

PS D:\PShell> Get-ChildItem | Get-Member -Name BaseName | Format-List -property TypeName, Definition


TypeName   : System.IO.DirectoryInfo
Definition : System.Object BaseName {get=$this.Name;}

TypeName   : System.IO.FileInfo
Definition : System.Object BaseName {get=if ($this.Extension.Length -gt 
             0){$this.Name.Remove($this.Name.Length - 
             $this.Extension.Length)}else{$this.Name};}

Ma réponse initiale était basée sur un malentendu impardonnable:

Lire dir /?, utiliser dir /A:-D:

/A          Displays files with specified attributes.
attributes   D  Directories                R  Read-only files
             H  Hidden files               A  Files ready for archiving
             S  System files               I  Not content indexed files
             L  Reparse Points             -  Prefix meaning not

Une autre approche: appliquer findstrregex en tant quedir *.* | findstr /V "<.*>"

JosefZ
la source
ce qui m'intéresse, c'est pourquoi *.*correspond à tous les fichiers , comme indiqué dans la question
phuclv
Je crains que votre suggestion alternative (findstr) ne trouve pas les dossiers qui commencent par un .semblable .dbus-keyrings, .VirtualBoxet .vscode.
22
Donc, dir /A:-Drépertorie uniquement les fichiers qui sont heureux?
Quentin
4
"Y a-t-il un moyen de ne lister que les fichiers avec un point?" dir /A:-Dest incorrect. 1 / il répertorie les fichiers sans extension. 2 / il ne répertorie pas les répertoires qui ont un .nom (parfaitement légal)
DavidPostill
3
omg ... ça fait des décennies que j'ai vu pour la dernière fois "@echo off"
rupps
7

Est-il possible de ne lister que les fichiers avec un point?

Vous pouvez faire correspondre les noms de fichiers avec un point en utilisant le caractère générique non documenté <, qui correspond à une séquence de 0 caractères ou plus dans le nom de base ou à une séquence de 0 caractères ou plus dans l'extension:

dir "<.<"

Rappelez-vous qu’il <s’agit également d’un métacaractère, vous devez donc le citer ou l’échapper à chaque utilisation de celui-ci dans un motif à partir du shell de commande.

feersum
la source
1
excellent. Ce wildcard non documenté existe bel et bien
phuclv
1

L'interpréteur de ligne de commande verra " . " Comme "Tous les noms de fichiers de base" avec "toutes les extensions". Une extension vide est toujours une extension , elle sera donc mise en correspondance et renvoyée avec la liste. Comme d'autres l'ont expliqué, il s'agit d'une survivance de versions antérieures de Windows et de MS-DOS.

Si vous préférez utiliser PowerShell, il est beaucoup plus facile de rechercher ces fichiers. Notez que dans PowerShell, "dir" est un alias de la cmdlet "Get-ChildItem".

Pour trouver tous les fichiers (pas les répertoires / dossiers) ayant une extension (par exemple, "myfile.txt", mais pas "FileWithNoExt"):

dir -af | Where {$_.Name -match "\."}

le commutateur "-af" est un raccourci pour "-Fichier" qui limite les objets renvoyés aux fichiers. "-ad" n'obtiendrait que des répertoires. Le "\." signifie "un caractère littéral". Sans la barre oblique inverse, le point correspondrait à n'importe quel caractère, comme dans les expressions rationnelles standard.

Pour obtenir tous les fichiers contenant un point dans le nom sans extension, ainsi qu'une extension (par exemple, "myDocument_v1.1.doc" mais pas "myfile.txt"):

dir -af | Where {$_.BaseName -match "\."}

Notez cependant que cela exclura un fichier avec le nom tel que ".archive" avec un point précédent. Ceci est dû au fait qu'il est traité comme n'ayant pas de nom de base et une extension "archive". Si vous souhaitez inclure ces éléments:

dir -af | Where {$_.BaseName -match "\.|^$"}

Ici, le motif de correspondance indique "Un point littéral, OU (|) BeginningOfString (^) suivi de EndOfString ($) (c'est-à-dire une chaîne vide)". Comme un fichier ne peut avoir à la fois un nom de base et une extension vide , il trouvera les fichiers commençant par un point.

Dave_J
la source
dans PowerShell, ls *.*c'est assez, comme beaucoup d'autres ont répondu avant vous
phuclv
-2

Si vous tapez la commande ci-dessus, alors voici: * (il s'agit d'un caractère générique qui signifie toute séquence de caractères) suivi d'un point (.) Suivi de * cela pourrait être interprété comme indiquant tous les fichiers portant le même nom (toute séquence de caractères (toute séquence de caractères), ce qui signifie en outre que tous les fichiers, quelle que soit leur extension, sont affichés.

Rahul Kant
la source
1
Alors pourquoi est Program Filesinclus dans la liste? Cela ne correspond pas au motif <sequence of characters>.<sequence of characters>.
Gronostaj
Pensez-y plus à <séquence de zéro caractère ou plus>. C'est pourquoi il prendrait également un fichier appelé ".info" où le nom de base est vide.
Dave_J