Чому `dir *. *` Надає мені всі файли та папки?


62

Коли я запускаю, dir *.*це дає несподівані результати. Навіть файли та папки без крапки в їх назвах перераховані. Наприклад

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

Чому так? Чи є спосіб перерахувати лише файли з крапкою?


19
Крапка завжди є, вона просто не надрукована, якщо за нею є щось. Іншими словами, ви можете подумати, що файл названий "це мій файл", але таємно ім'я: "це мій файл". без нічого після крапки. Аналогічно, ви можете подумати, що назва DNS для цього сайту - «superuser.com», але насправді це «superuser.com». без нічого після другої крапки.
Тодд Вілкокс

12
@ToddWilcox правильний лише в DOS. Сучасні файлові системи в Windows більше не мають окремого простору імен розширень
phuclv

13
@ LưuVĩnhPhúc Підсистема Win32 розглядає назви файлів, які не містять .подібних, які вони мають .у підсумку для багатьох цілей, включаючи цю.
CodesInChaos

2
Папки, які не містять .символу, мають на увазі .символ в кінці. - Наприклад, у вас може бути папка з назвою "Blah.old", і тоді вона матиме традиційне розширення файлу на 3 літери; для щоденного використання, хоча " Blah" це те саме, що " Blah." це файл чи папка.
BrainSlugs83

9
@ can-ned_food Тод Вілкокс вірно стосується DNS. Кореневу зону DNS називають буквально ., а мітки в іменах DNS відокремлюють .(таким чином, назва кореневої зони DNS є єдиною міткою нульової довжини). Одна дитина кореневої зони DNS .є com., а одна дитина - com.це superuser.com.тощо.
CVn

Відповіді:


115

Я пишу цю відповідь, тому що ОП підкреслив, що:

що мене цікавить, чому вони *.*відповідають усім файлам, як зазначено в запитанні

DIRКоманда приходить від часу , коли:

  1. Період (.) Не було дозволено як символ у назвах файлів чи папок
  2. Імена файлів і папок мали обмеження до 8 символів для імені та 3 символів для розширень

Тому під цим стандартом *.*малося на увазі незалежно від назви та будь-якого розширення . Це не означало рядок, що містить ".", Яка може мати або не мати символів до або після ". .

Політика Microsoft зберігає зворотну сумісність. Отже, ця інтерпретація *.*зберігається.

Але в Windows PowerShell *.*означає рядок, що містить ".", Яка може мати або не мати символів до або після ". .



25
Оригінальна файлова система навіть не зберігала сам період на диску, лише 11 символів складали решту імені.
Містер Лістер

7
Варто зазначити, що файли та папки без розширень як і раніше вважаються порожніми розширеннями . Тому папка з назвою " Folder." і папка з назвою " Folder" називаються однаково, що стосується Windows.
BrainSlugs83

2
@MrLister Цікаво. Як старі імена файлів FS зберігали на зразок AA.BB<8 у першій частині та <3 у розширенні? Це просто колодка з пробілами?
Келвін

3
@Kelvin так, обидві частини були окремо прокладені космосом.
plugwash

12

Чому так?

Відповідь на " Чому це? " Можна знайти у статті 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)

Правила відповідності підстановок

  • *Зазвичай відповідає будь-якому 0 або більше символів, за винятком одного (див. Наступне правило). Не жадібна підстановка може зіставити стільки або менше символів, скільки потрібно, щоб залишки маски відповідали.

  • *.В кінці маски відповідає будь-яке 0 або більше символів, крім {dot}. Насправді це правило застосовується до будь-якої кількості символів {dot} та {space} між * та терміналом {dot}. Регулярним виразом цього терміна є"[*][. ]*[.]$"

  • ?Збіг 0 або один символ, за винятком {dot}. Єдиний раз, коли він відповідає 0 символам, це коли він відповідає кінці імені або позиції перед {крапкою}. Знак питання також може використовуватися не один раз, щоб відповідати більш ніж одному символу.

Наслідки . Останній {точка} в імені файлу / папки відокремлює базове ім'я і розширення. Тому

  • dir *.відображає всі елементи без розширення та
  • dir *.*відображає всі елементи з розширенням нуля або більше символів .

Власне кажучи, dir *.відображаються всі елементи без. назви ( ) у назві . (BTW, Ім'я файлів, Шляхів та просторів імен Стаття MSDN прямо говорить про те, що " прийнятно вказати період як перший символ імені ".)

Чи є спосіб перерахувати лише файли з крапкою?

Я не думаю, що так. Однак є вирішення відповідного регулярного виразу.

PowerShell (рішення повного масштабу, якщо використовується в консолі Powershell):

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

Cmd (лише ідея, може знадобитися певна розробка):

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

Додаток: премія та пояснення

Інтуїтивно зрозуміла здогадка, яка Nameє об'єднаною BaseNameі Extension не дотримується . Наступний сценарій доводить це за допомогою основних cmdі PowerShellосновних функцій, і дивний ^..*\...*$ регулярний вираз виходить з його результатів.

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

Вихід :

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

Порівняйте визначення BaseNameвластивостей, різних для файлів і папок:

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

Моя оригінальна відповідь ґрунтувалася на непрощенному непорозумінні:

Прочитайте dir /?, використовуйте 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

Інший підхід: застосувати findstrрегулярне вираження якdir *.* | findstr /V "<.*>"


що мене цікавить, чому *.*відповідає всім файлам , як зазначено у запитанні
phuclv

Я боюся, що ваша альтернативна пропозиція (findstr) не знайде папок, які починаються з .подібних .dbus-keyrings, .VirtualBoxі .vscode.

22
Тож dir /A:-Dперераховуються лише ті файли, які раді?
Квентін

4
"Чи є спосіб перерахувати лише файли з крапкою?" dir /A:-Dневірно. 1 / в ньому перераховані файли без розширення. 2 / у ньому не .
вказані

3
omg ... минуло десятиліття з моменту, коли я востаннє бачив "@echo off"
rupps

7

Чи є спосіб перерахувати лише файли з крапкою?

Ви можете зіставити назви файлів з крапкою, використовуючи незадокументований підстановочний код <, який відповідає послідовності 0 або більше символів у базовій імені, або послідовності 0 або більше символів у розширенні:

dir "<.<"

Пам’ятайте, що <це також метахарактер, тому вам потрібно його цитувати або уникати кожного разу, використовуючи його у шаблоні з оболонки команди.


1
відмінна. Ця незадокументована маска дійсно існує
phuclv

1

Інтерпретатор командного рядка побачить " . " Як "Усі базові імена файлів" із "усіма розширеннями". Порожнє розширення все ще є розширенням , тому воно буде відповідне і повернене зі списком. Як пояснили інші, це похмілля попередніх версій Windows та MS-DOS.

Якщо ви з радістю виглядаєте за допомогою PowerShell, знайти ці файли набагато простіше. Зауважте, що в PowerShell "dir" є псевдонімом для командлета "Get-ChildItem".

Щоб знайти всі файли (не каталоги / папки), які мають розширення (наприклад, "myfile.txt", але не "FileWithNoExt"):

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

перемикач "-af" є скороченням для "-File", що обмежує повернення об'єктів лише файлами. "-ad" отримував би лише каталоги. Значення "\". означає "буквальний крапковий символ". Без зворотної косої риски точка буде відповідати будь-якому символу, як за стандартним регулярним виразом.

Щоб отримати всі файли, де в імені була точка без розширення, а також розширення (наприклад, "myDocument_v1.1.doc", але не "myfile.txt"):

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

Однак зауважте, що це виключить файл із назвою типу ".archive" з попередньою крапкою. Це тому, що це трактується як відсутність базового імені та розширення "архіву". Якщо ви хочете включити такі:

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

Тут шаблон відповідності говорить "Буквальна крапка, АБО (|) BeginningOfString (^), за якою закінчується EndOfString ($) (тобто порожній рядок)". Оскільки файл не може мати порожнє базове ім'я та розширення, він знайде файли, починаючи з крапки.


в PowerShell просто ls *.*достатньо, як багато інших відповіли перед вами
phuclv

-2

Якщо ви введете вище команду, то тут: * (це підказка, яка означає будь-яку послідовність символів), а потім крапка (.), А потім * це може бути інтерпретовано як показ усіх файлів, які мають ім'я типу (будь-яка послідовність символів (будь-яка послідовність символів), що додатково означає, що показують усі файли з будь-яким розширенням.


1
Тоді чому Program Filesвключається до списку? Це не відповідає шаблону <sequence of characters>.<sequence of characters>.
gronostaj

Подумайте про це більше як <Послідовність нуля або більше символів> Ось чому він також підбере файл під назвою ".info", де ім'я бази порожнє.
Dave_J
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.