Por que 'dir *. *' me fornece todos os arquivos e pastas?

60

Quando executo dir *.* , ele produz resultados inesperados. Mesmo arquivos e pastas sem qualquer ponto em seus nomes são listados. Por exemplo

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

Por que isso? Existe alguma maneira de listar apenas arquivos com um ponto?

    
por phuclv 28.03.2017 / 11:58

5 respostas

114

Estou escrevendo esta resposta porque OP enfatizou que:

what I'm interested is why *.* matches all files, as stated in the question

O comando DIR vem de um momento em que:

  1. O período (.) não foi permitido como um caractere em nomes de arquivos ou pastas
  2. Os nomes de arquivos e pastas estavam restritos a 8 caracteres para nome e 3 caracteres para extensões

Portanto, por esse padrão, *.* significava qualquer que fosse o nome e a extensão . não significa uma string contendo um ".", Que pode ou não ter caracteres antes ou depois do "." .

A política da Microsoft está preservando a compatibilidade com versões anteriores. Portanto, essa interpretação de *.* é mantida.

Mas no Windows PowerShell, *.* significa uma string contendo um ".", que pode ou não ter caracteres antes ou depois do "." .

    
por 28.03.2017 / 12:47
11

Por que isso acontece?

Pode-se encontrar uma resposta para " Por que isso? " em Wildcards < Artigo / strong> :

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)

Wildcard matching rules

  • * Generally matches any 0 or more characters, with one exception (see next rule). The non-greedy wildcard is free to match as many or as few characters as are necessary for the remainder of the mask to match.

  • *. At end of mask matches any 0 or more characters except for {dot}. In actuality, the rule applies with any number of {dot} and {space} characters between the * and terminal {dot}. The regular expression for this term is "[*][. ]*[.]$"

  • ? Match 0 or one character, except for {dot}. The only time it matches 0 characters is when it matches the end of the name, or the position before a {dot}. The question mark can also be used more than once to match more than one character.

Implicação . O último {dot} em um nome de arquivo / pasta separa nome e extensão base. Então

  • dir *. exibe todos os itens com sem extensão e
  • dir *.* exibe todos os itens com extensão de zero ou mais caracteres .

Estritamente falando, dir *. exibe todos os itens com sem período ( . ) no nome . (BTW, Nomeando arquivos, caminhos e namespaces Artigo MSDN diz explicitamente que " é aceitável especificar um período como o primeiro caractere de um nome ".

Existe alguma maneira de listar apenas arquivos com um ponto?

Eu não penso assim. No entanto, há uma solução alternativa com uma expressão regular adequada.

PowerShell (solução de escopo total, se usada em um 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 (apenas uma ideia, pode exigir alguma elaboração):

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

Adendo: um bônus e uma explicação

Um palpite intuitivo de que Name está concatenado BaseName e Extension não é válido . O script a seguir prova isso usando os recursos cmd e PowerShell core, e o estranho ^..*\...*$ regex é derivado de seus resultados.

@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}"

Saída :

==> 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

Comparar a definição da propriedade BaseName , diferente para arquivos e pastas:

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};}

Minha resposta original foi baseada em mal-entendidos imperdoáveis:

Leia dir /? , use 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

Outra abordagem: aplique findstr regex como dir *.* | findstr /V "<.*>"

    
por 28.03.2017 / 12:20
6

Is there any way to list only files with a dot?

Você pode corresponder nomes de arquivos com um ponto usando o caractere curinga não documentado < , que corresponde a uma sequência de 0 ou mais caracteres no nome da base ou a uma sequência de 0 ou mais caracteres na extensão:

dir "<.<"

Lembre-se de que < também é um meta-caractere, portanto, é necessário citar ou escapar sempre que for usado em um padrão a partir do shell de comando.

    
por 30.03.2017 / 12:04
1

O Interpretador de Linha de Comando verá ". " como "Todos os nomes de arquivos base" com "todas as extensões". Uma extensão em branco é ainda uma extensão , portanto, será correspondida e retornada com a lista. Como outros explicaram, esta é uma ressaca de versões anteriores do Windows e do MS-DOS.

Se você estiver feliz em procurar usando o PowerShell, encontrar esses arquivos é muito mais fácil. Observe que, no PowerShell, "dir" é um alias para o cmdlet "Get-ChildItem".

Para localizar todos os arquivos (não diretórios / pastas) que tenham uma extensão (por exemplo, "myfile.txt", mas não "FileWithNoExt"):

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

a opção "-af" é uma abreviação de "-File", que restringe os objetos de retorno somente aos arquivos. "-ad" só obteria diretórios. O "\." significa "um caractere de ponto literal". Sem a barra invertida, o ponto corresponderia a qualquer caractere, de acordo com a regex padrão.

Para obter todos os arquivos em que havia um ponto no nome sem a extensão, bem como uma extensão (por exemplo, "myDocument_v1.1.doc", mas não "myfile.txt"):

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

No entanto, observe que isso excluirá um arquivo com o nome, como ".archive", com um ponto precedente. Isso ocorre porque é tratado como não tendo nenhum nome de base e uma extensão de "archive". Se você quiser incluir estes:

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

Aqui, o padrão de correspondência diz "Um ponto literal, OR (|) BeginningOfString (^) seguido por EndOfString ($) (ou seja, uma string vazia)". Como um arquivo não pode ter uma extensão de nome de base vazia e , ele encontrará os arquivos que começam com um ponto.

    
por 29.03.2017 / 18:56
-2

Se você digitar o comando acima, clique aqui:  * (este é um curinga que significa qualquer seqüência de caracteres) seguido por um ponto (.) seguido por * isso pode ser interpretado como mostrar todos os arquivos que têm nome como (qualquer seqüência de caracteres). caracteres) que significa ainda que mostra todos os arquivos com qualquer extensão.

    
por 29.03.2017 / 22:27