61

Когда я запускаю 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

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

5 ответов5

115

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

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

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

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

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

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

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

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

  • ? Совпадение 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 @{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 "<.*>"

6

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

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

dir "<.<"

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

1

Интерпретатор командной строки увидит « . » Как "Все базовые имена файлов" со "всеми расширениями". Пустое расширение все еще является расширением, поэтому будет сопоставлено и возвращено со списком. Как объяснили другие, это похмелье от более ранних версий 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($) (т.е. пустая строка)». Поскольку файл не может иметь как пустое базовое имя, так и расширение, он найдет файлы, начинающиеся с точки.

-2

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .