Почему `dir *. *` Дает мне все файлы и папки?

8938
phuclv

Когда я бегу, 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 

Это почему? Есть ли способ перечислить только файлы с точкой?

60
Точка всегда есть, она просто не печатается, если за ней что-то не идет. Другими словами, вы можете подумать, что файл называется «это мой файл», но в тайне он называется «это мой файл». ни с чем после точки. Аналогично, вы можете подумать, что DNS-имя для этого сайта - «superuser.com», но на самом деле это «superuser.com». ни с чем после второй точки. Todd Wilcox 7 лет назад 17
@ToddWilcox это правильно только в DOS. Современные файловые системы в Windows больше не имеют отдельного пространства имен расширений phuclv 7 лет назад 11
@ LưuVĩnhPhúc Подсистема Win32 обрабатывает имена файлов, которые не содержат `.`, как они имеют` .` в конце для многих целей, включая эту. CodesInChaos 7 лет назад 12
Папки, которые не содержат символ `.`, в конце имеют подразумеваемый символ` .`. - У вас может быть папка с именем "Blah.old", например, и тогда у нее будет традиционное трехбуквенное расширение файла; для повседневного использования, хотя «Blah» - это то же самое, что «Blah», будь то файл или папка. BrainSlugs83 7 лет назад 2
@ToddWilcox Хм, я думаю, что это действительно смешивает несколько вещей. Насколько я знаю, информация о поиске DNS также неверна. Я думаю, что большинство из них выполняет простое перенаправление на основе правил, если вы запрашиваете имя хоста, подобное этому. can-ned_food 7 лет назад 0
@ can-ned_food Тодд Уилкокс прав насчет DNS. Корневая DNS-зона называется буквально `.`, а метки в DNS-именах разделяются` .` (таким образом, имя корневой DNS-зоны представляет собой одну метку нулевой длины). Один дочерний элемент корневой DNS-зоны `.` является` com`, а один дочерний элемент `com` -` superuser.com` и т. Д. a CVn 7 лет назад 8
Обратите внимание, что в Windows анализ подстановочных знаков является обязанностью команды, а не команды * Prompt *. Таким образом, правила расширения для одного инструмента командной строки могут отличаться от правил другого. Это отличается, скажем, от Linux, где обычно отвечает * shell * (при условии цитирования). Тем не менее, встроенные команды командной строки (включая `dir`,` copy`, `del` и т. Д.), Как правило, имеют одинаковые правила расширения (поскольку все они реализованы в одной программе - командной строке). jimbobmcgee 7 лет назад 0
Интересно, что по крайней мере в одной версии MS-DOS (MS-DOS 7.1, включенной в Windows 95 OEM Service Release 2 или новее и во всех версиях Windows 98) команда `dir.exe` (например) анализируется как `dir * .exe`; насколько я могу судить, такого поведения нет в командной строке Windows NT. Justin Time 7 лет назад 0
@jimbobmcgee Windows API обрабатывает расширение подстановочных знаков с помощью своего семейства функций `FindFirstFile` (и его семейства оболочек` _findfirst` в библиотеке времени выполнения C), поэтому любая программа, использующая его, будет иметь такое же расширение подстановочных знаков. Medinoc 7 лет назад 1
Эта информация полезна при попытке [сохранить .htaccess из notepad.exe] (http://stackoverflow.com/questions/5004633/how-to-manually-create-a-file-with-a-dot-prefix- in-windows-for-example-htacce) в Windows. _Или любой другой файл точек_ TecBrat 7 лет назад 0

5 ответов на вопрос

114
jpaugh

Я пишу этот ответ, потому что ОП подчеркнул, что:

что меня интересует, почему *.*совпадает со всеми файлами, как указано в вопросе

Команда DIRприходит со времени, когда:

  1. Точка (.) Не допускается в качестве символа в именах файлов или папок
  2. Имена файлов и папок были ограничены 8 символами для имени и 3 символами для расширений

Следовательно, под этим стандартом *.*подразумевается любое имя и любое расширение . Это не означает строку, содержащую «.», Которая может содержать или не содержать символы до или после «.» ,

Политика Microsoft сохраняет обратную совместимость. Следовательно, это толкование *.*сохраняется.

Но в Windows PowerShell *.*означает строку, содержащую «.», Которая может содержать или не содержать символы до или после «.» ,

Дополнительное чтение: https://blogs.msdn.microsoft.com/oldnewthing/20071217-00/?p=24143 grawity 7 лет назад 9
Оригинальная файловая система даже не сохраняла сам период на диске, только 11 символов составляют остальную часть имени. Mr Lister 7 лет назад 24
Стоит отметить, что файлы и папки без расширений по-прежнему рассматриваются как имеющие ** пустое расширение **. Следовательно, папка с именем «Папка» и папка с именем «Папка» имеют одно и то же имя в отношении окон. BrainSlugs83 7 лет назад 7
@ BrainSlugs83 Ну, это зависит от того, какая часть Windows. У меня была неприятная ошибка, когда я сохранял файл из IE11 с `.` в конце его имени. Я понятия не имею, что сисадмины сделали, чтобы исправить это, но вместо этого предпринимались какие-либо действия в отношении файла «file» в Windows Explorer, поэтому я не мог удалить все дерево каталогов. Вероятно, они использовали Powershell, потому что (как показано в этом ответе), который не имеет «совместимости с именами совместимости», как у большинства Windows. wizzwizz4 7 лет назад 0
@MrLister Интересно. Как старая ФС хранила имена файлов, такие как `AA.BB` с <8 в первой части и <3 в расширении? Это просто с пробелами? Kelvin 7 лет назад 2
@ Кельвин, да, две части были разделены пробелами. plugwash 7 лет назад 3
@ Кельвин Да. Нравится AA␣␣␣␣␣␣BB␣ Mr Lister 7 лет назад 0
@Kelvin Если вас интересуют все (старые) кровавые подробности, см. [Страницы 6/7 этого PDF] (http://www.eit.lth.se/fileadmin/eit/courses/eitn50/Projekt1/FAT12Description .pdf) TripeHound 7 лет назад 0
@ BrainSlugs83 Не так. https://i.imgur.com/710MUG7.png DavidPostill 7 лет назад 2
@DavidPostill Но смотрите: http://imgur.com/UgmX8xi Они одинаковы для одних целей и не одинаковы для других. Ross Presser 7 лет назад 2
Все это изначально было сделано для того, чтобы эмулировать CP / M, который делал то же самое. Это было затем переработано в MS-DOS 2, чтобы дать что-то намного ближе к тому, что мы знаем сегодня. Это также причина того, что \ используется вместо / как в Unix, потому что / уже использовалось в CP / M для указания параметров командной строки. Thorbjørn Ravn Andersen 7 лет назад 0
11
JosefZ

Это почему?

Ответ на вопрос « Почему это так? » Можно найти в статье 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 или более символов, кроме . В действительности, правило применяется с любым количеством символов и между * и терминалом . Регулярное выражение для этого термина"[*][. ]*[.]$"

  • ?Совпадение 0 или один символ, кроме . Единственный раз, когда он соответствует 0 символам, это когда он соответствует концу имени или позиции перед точкой . Знак вопроса также может использоваться более одного раза, чтобы соответствовать более чем одному символу.

Смысл . Последний в имени файла / папки отделяет базовое имя и расширение. Так

  • dir *.отображает все элементы без расширения и
  • dir *.*отображает все элементы с расширением от нуля или более символов .

Строго говоря, dir *.отображает все элементы без точки ( .) в имени . (Кстати, в статье 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 @, @" 

Выход :

==> 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 @, @"  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   TypeName : System.IO.FileInfo Definition : System.Object BaseName 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 7 лет назад 0
Боюсь, ваше альтернативное предложение (findstr) не находит папки, начинающиеся с `.`, например` .dbus-keyrings`, `.VirtualBox` и` .vscode`. 7 лет назад 0
Итак, `dir / A: -D` перечисляет только файлы, которые счастливы? Quentin 7 лет назад 21
"Есть ли способ перечислить только файлы с точкой?" `dir / A: -D` неверно. 1 / в нем перечислены файлы без расширения. 2 / в нем нет каталогов, в названии которых есть `.` (совершенно законно) DavidPostill 7 лет назад 4
@ LưuVĩnhPhúc Неверные части этого вопроса в стороне, в первую очередь он отвечает на функциональную часть вашего вопроса - «Есть ли какой-нибудь путь» - что, как я ожидаю, будет вашей главной заботой; «почему» в вашем названии кажется излишним. can-ned_food 7 лет назад 0
@ can-ned_food - это второстепенная вещь, которую я хочу знать, как результат результата команды. То, что я спрашиваю, это жирный текст в верхней части этой страницы phuclv 7 лет назад 0
`dir * .` отображает все файлы и папки без расширения, а не только папки. `dir *. *` также список файлов и папок phuclv 7 лет назад 0
о боже ... прошло уже несколько десятилетий с тех пор, как я последний раз видел "@echo off" rupps 7 лет назад 3
6
feersum

Есть ли способ перечислить только файлы с точкой?

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

dir "<.<" 

Помните, что <это также метасимвол, поэтому вы должны заключать его в кавычки или экранировать всякий раз, когда используете его в шаблоне из командной оболочки.

отлично. Этот [недокументированный подстановочный знак] (https://ss64.com/nt/syntax-wildcards.html) действительно существует phuclv 7 лет назад 0
1
Dave_J

Интерпретатор командной строки увидит « . » Как «Все базовые имена файлов» со «всеми расширениями». Пустое расширение все еще является расширением, поэтому будет сопоставлено и возвращено со списком. Как объяснили другие, это похмелье от более ранних версий Windows и MS-DOS.

Если вы счастливы смотреть с помощью PowerShell, найти эти файлы намного проще. Обратите внимание, что в PowerShell «dir» является псевдонимом командлета «Get-ChildItem».

Чтобы найти все файлы (не каталоги / папки), которые имеют расширение (например, «myfile.txt», но не «FileWithNoExt»):

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

ключ "-af" является сокращением для "-File", который ограничивает возвращаемые объекты только файлами. «-ад» получит только каталоги. "\" означает «буквальная точка». Без обратной косой черты точка будет соответствовать любому символу в соответствии со стандартным регулярным выражением.

Чтобы получить все файлы, в имени которых была точка, без расширения, а также с расширением (например, «myDocument_v1.1.doc», но не «myfile.txt»):

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

Однако обратите внимание, что это исключит файл с именем, таким как «.archive» с предшествующей точкой. Это потому, что он рассматривается как не имеющий базового имени и расширения «архив». Если вы хотите включить это:

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

Здесь шаблон совпадения говорит: «Буквальная точка, OR (|) BeginningOfString (^), за которой следует EndOfString ($) (т.е. пустая строка)». Поскольку файл не может иметь как пустое базовое имя, так и расширение, он найдет файлы, начинающиеся с точки.

в PowerShell достаточно `ls *. *`, так как многие другие ответили перед вами phuclv 6 лет назад 0
-2
Rahul Kant

Если вы введете указанную выше команду, то здесь: * (это подстановочный знак, означающий любую последовательность символов), за которым следует точка (.), За которой следует *, это можно интерпретировать как показывать все файлы, имена которых похожи (любая последовательность символов) ). (любая последовательность символов), что дополнительно означает, что отображаются все файлы с любым расширением.

Тогда почему «Program Files» включен в список? Это не соответствует шаблону `,`. gronostaj 7 лет назад 1
Думайте об этом больше как Поэтому он также выберет файл с именем .info, в котором базовое имя будет пустым. Dave_J 7 лет назад 0