Perché `dir *. *` Mi dà tutti i file e le cartelle?


62

Quando corro dir *.*produce risultati inaspettati. Vengono elencati anche file e cartelle senza punti nei loro nomi. Per esempio

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

Perché? C'è un modo per elencare solo i file con un punto?


19
Il punto è sempre lì, non viene stampato a meno che non ci sia qualcosa che lo segue. In altre parole, potresti pensare che un file si chiami "questo è il mio file" ma segretamente il nome è "questo è il mio file". con niente dopo il punto. Analogamente, potresti pensare che il nome DNS per questo sito sia "superuser.com", ma in realtà è "superuser.com". con niente dopo il secondo punto.
Todd Wilcox,

12
@ToddWilcox è corretto solo in DOS. I moderni filesystem in Windows non hanno più uno spazio dei nomi di estensione separato
phuclv,

13
@ LưuVĩnhPhúc Il sottosistema Win32 tratta i nomi di file che non contengono un .simile .alla fine per molti scopi, incluso questo.
Codici

2
Le cartelle che non contengono il .personaggio hanno un .carattere implicito alla fine. - Puoi avere una cartella chiamata "Blah.old" per esempio, e poi avrebbe una tradizionale estensione di file di 3 lettere; per l'uso quotidiano sebbene " Blah" sia uguale a " Blah." sia che si tratti di un file o di una cartella.
BrainSlugs83

9
@ can-ned_food Todd Wilcox ha ragione sul DNS. La zona DNS radice viene definita letteralmente .e le etichette nei nomi DNS sono separate da .(quindi il nome della zona DNS radice è una singola etichetta di lunghezza zero). Un figlio della zona DNS radice .è com., un figlio di com.è superuser.com.e così via.
un CVn il

Risposte:


115

Sto scrivendo questa risposta perché OP ha sottolineato che:

quello che mi interessa è perché *.*corrisponde a tutti i file, come indicato nella domanda

Il DIRcomando proviene da un momento in cui:

  1. Il punto (.) Non era consentito come carattere nei nomi di file o cartelle
  2. I nomi di file e cartelle erano limitati a 8 caratteri per nome e 3 caratteri per estensioni

Pertanto, per quello standard, *.*intendeva qualunque sia il nome e qualunque fosse l'estensione . Non significava una stringa contenente un ".", Che può avere o meno caratteri prima o dopo il "." .

La politica di Microsoft mantiene la compatibilità con le versioni precedenti. Pertanto, tale interpretazione di *.*viene mantenuta.

Ma in Windows PowerShell, *.*significa una stringa contenente un ".", Che può avere o meno caratteri prima o dopo il "." .



25
Il file system originale non ha nemmeno memorizzato il periodo stesso sul disco, solo gli 11 caratteri che compongono il resto del nome.
Lister,

7
Vale la pena notare che i file e le cartelle senza estensioni vengono comunque trattati con un'estensione vuota . Pertanto, una cartella denominata " Folder." e una cartella denominata " Folder" sono denominate la stessa cosa, per quanto riguarda Windows.
BrainSlugs83

2
@MrLister Interessante. In che modo i vecchi file FS memorizzavano i nomi dei file AA.BBcon <8 nella prima parte e <3 nell'estensione? Ha appena riempito di spazi?
Kelvin,

3
@Kelvin sì, le due parti erano imbottite separatamente nello spazio.
lavaggio:

12

Perché?

Si potrebbe trovare una risposta a " Why is that? " Nell'articolo Wildcard :

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)

...

Regole di corrispondenza dei caratteri jolly

  • *Generalmente corrisponde a qualsiasi 0 o più caratteri, con una sola eccezione (vedere la regola successiva). Il carattere jolly non avido è libero di abbinare tutti i caratteri necessari per il resto della maschera.

  • *.Alla fine della maschera corrisponde a qualsiasi 0 o più caratteri tranne {punto}. In realtà, la regola si applica con qualsiasi numero di caratteri {punto} e {spazio} tra * e il terminale {punto}. L'espressione regolare per questo termine è"[*][. ]*[.]$"

  • ?Abbina 0 o un carattere, tranne {punto}. L'unica volta che corrisponde a 0 caratteri è quando corrisponde alla fine del nome o alla posizione prima di un {punto}. Il punto interrogativo può anche essere usato più di una volta per abbinare più di un personaggio.

Implicazioni . L' ultimo {punto} nel nome di un file / cartella separa il nome di base e l'estensione. Così

  • dir *.visualizza tutti gli elementi senza estensione e
  • dir *.*visualizza tutti gli elementi con estensione di zero o più caratteri .

A rigor di termini, dir *.visualizza tutti gli elementi senza punto ( .) nel nome . (BTW, File di denominazione, Percorsi e Namespace L' articolo MSDN afferma esplicitamente che " è accettabile specificare un punto come primo carattere di un nome ".)

C'è un modo per elencare solo i file con un punto?

Io non la penso così. Tuttavia, esiste una soluzione alternativa con un'espressione regolare adatta.

PowerShell (soluzione full scope se utilizzata in una 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 (solo un'idea, potrebbe richiedere qualche elaborazione):

:: 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 e una spiegazione

Un'ipotesi intuitiva che Nameè concatenata BaseNamee Extension non regge . Lo script che segue lo dimostra usando cmde PowerShellle caratteristiche di base, e la strana ^..*\...*$ espressione regolare è derivato dal suo risultato.

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

Uscita :

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

Confronta la definizione di BaseNameproprietà, diversa per file e cartelle:

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

La mia risposta originale era basata su incomprensioni imperdonabili:

Leggi dir /?, usa 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

Un altro approccio: applicare findstrregex comedir *.* | findstr /V "<.*>"


quello che mi interessa è perché *.*corrisponde a tutti i file , come indicato nella domanda
phuclv,

Temo la tua proposta alternativa (findstr) non trova cartelle che iniziano con una .simile .dbus-keyrings, .VirtualBoxe .vscode.

22
Quindi dir /A:-Delenca solo i file che sono felici?
Quentin,

4
"Esiste un modo per elencare solo i file con un punto?" dir /A:-Dnon è corretto. 1 / elenca i file senza estensione. 2 / non elenca le directory che hanno un .nome proprio (perfettamente legale)
DavidPostill

3
omg ... sono passati decenni dall'ultima volta che ho visto "@echo off"
rupps il

7

C'è un modo per elencare solo i file con un punto?

Puoi abbinare i nomi dei file a un punto usando il carattere jolly non documentato <, che corrisponde a una sequenza di 0 o più caratteri nel nome di base o a una sequenza di 0 o più caratteri nell'estensione:

dir "<.<"

Ricorda che <è anche un metacarattere, quindi è necessario citare o scappare ogni volta che lo si utilizza in un modello dalla shell dei comandi.


1
eccellente. Questo jolly senza documenti esiste davvero
phuclv

1

L'interprete della riga di comando vedrà " . " Come "Tutti i nomi dei file di base" con "tutte le estensioni". Un'estensione vuota è ancora un'estensione , quindi verrà abbinata e restituita con l'elenco. Come altri hanno spiegato, si tratta di postumi di una sbornia da versioni precedenti di Windows e MS-DOS.

Se sei felice di guardare usando PowerShell, trovare questi file è molto più semplice. Si noti che in PowerShell "dir" è un alias per il cmdlet "Get-ChildItem".

Per trovare tutti i file (non directory / cartelle) con estensione (ad es. "Myfile.txt", ma non "FileWithNoExt"):

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

l'opzione "-af" è una scorciatoia per "-File" che limita gli oggetti di ritorno solo ai file. "-ad" otterrebbe solo le directory. Il "\." significa "un carattere punto letterale". Senza la barra rovesciata, il punto corrisponderebbe a qualsiasi carattere, come da regex standard.

Per ottenere tutti i file in cui era presente un punto nel nome senza l'estensione, nonché un'estensione (ad esempio "myDocument_v1.1.doc" ma non "myfile.txt"):

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

Si noti tuttavia che ciò escluderà un file con il nome come ".archive" con un punto precedente. Questo perché viene considerato come non avere un nome di base e un'estensione di "archivio". Se vuoi includere questi:

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

Qui, il modello di corrispondenza dice "Un punto letterale, OR (|) BeginningOfString (^) seguito da EndOfString ($) (ovvero una stringa vuota)". Poiché un file non può avere sia un nome di base vuoto che un'estensione, troverà i file che iniziano con un punto.


in PowerShell ls *.*è sufficiente, come molti altri hanno risposto prima di te
phuclv,

-2

Se si digita il comando sopra, quindi qui: * (questo è un carattere jolly che significa qualsiasi sequenza di caratteri) seguito da un punto (.) Seguito da * questo potrebbe essere interpretato come mostra tutti i file che hanno un nome simile (qualsiasi sequenza di caratteri ) (qualsiasi sequenza di caratteri) che significa inoltre che mostra tutti i file con qualsiasi estensione.


1
Allora perché è Program Filesincluso nell'elenco? Non corrisponde allo schema <sequence of characters>.<sequence of characters>.
gronostaj,

Pensalo più come <Sequenza di zero o più caratteri> Ecco perché dovrebbe anche prendere un file chiamato ".info" dove il nome di base è vuoto.
Dave_J,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.