Tại sao `dir *. *` Cung cấp cho tôi tất cả các tệp và thư mục?


62

Khi tôi chạy dir *.*nó tạo ra kết quả bất ngờ. Ngay cả các tệp và thư mục không có bất kỳ dấu chấm nào trong tên của chúng được liệt kê. Ví dụ

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

Tại sao vậy? Có cách nào để liệt kê chỉ các tệp có dấu chấm không?


19
Dấu chấm luôn ở đó, nó chỉ không được in trừ khi có cái gì đó theo sau nó. Nói cách khác, bạn có thể nghĩ rằng một tệp có tên "đây là tệp của tôi" nhưng bí mật tên là "đây là tệp của tôi." không có gì sau dấu chấm. Tương tự, bạn có thể nghĩ rằng tên DNS cho trang web này là "superuser.com", nhưng thực ra nó là "superuser.com". không có gì sau dấu chấm thứ hai.
Todd Wilcox

12
@ToddWilcox nó chỉ đúng trong DOS. Các hệ thống tệp hiện đại trong Windows không còn có một không gian tên mở rộng riêng biệt nữa
phuclv

13
@ LưuViênPhúc Hệ thống con Win32 xử lý tên tệp không chứa .giống như .cuối cùng cho nhiều mục đích, bao gồm cả mục đích này.
CodeInChaos

2
Các thư mục không chứa .ký tự có một .ký tự ngụ ý ở cuối. - Ví dụ, bạn có thể có một thư mục có tên "Blah.old", và sau đó nó sẽ có phần mở rộng tệp 3 chữ cái truyền thống; cho việc sử dụng hàng ngày mặc dù " Blah" giống như " Blah." cho dù đó là tệp hay thư mục.
BrainSlugs83

9
@ can-ned_food Todd Wilcox là chính xác về DNS. Vùng DNS gốc được gọi là nghĩa đen .và các nhãn trong tên DNS được phân tách bằng .(do đó tên của vùng DNS gốc là một nhãn có độ dài bằng không). Một trẻ em của vùng DNS gốc .com., và một đứa trẻ com.superuser.com., và vân vân.
một CVn

Câu trả lời:


115

Tôi viết câu trả lời này vì OP đã nhấn mạnh rằng:

Điều tôi quan tâm là tại sao *.*phù hợp với tất cả các tệp, như đã nêu trong câu hỏi

Các DIRlệnh xuất phát từ một thời gian khi:

  1. Dấu chấm (.) Không được phép dưới dạng ký tự trong tên tệp hoặc thư mục
  2. Tên tệp và thư mục được giới hạn ở 8 ký tự cho tên và 3 ký tự cho tiện ích mở rộng

Do đó, theo tiêu chuẩn đó, *.*có nghĩa là bất cứ tên nào và bất kỳ phần mở rộng nào . Nó không có nghĩa là một chuỗi chứa ".", Có thể có hoặc không có ký tự trước hoặc sau dấu "." .

Chính sách của Microsoft đang bảo tồn khả năng tương thích ngược. Do đó, giải thích đó *.*được giữ lại.

Nhưng trong Windows PowerShell, *.*có nghĩa là một chuỗi chứa ".", Có thể có hoặc không có ký tự trước hoặc sau dấu "." .



25
Hệ thống tệp gốc thậm chí không lưu trữ thời gian trên đĩa, chỉ có 11 ký tự tạo thành phần còn lại của tên.
Ông Lister

7
Cần lưu ý rằng các tệp và thư mục không có phần mở rộng vẫn được coi là có phần mở rộng trống . Do đó, một thư mục có tên " Folder." và một thư mục có tên " Folder" được đặt tên giống nhau, theo như các cửa sổ có liên quan.
BrainSlugs83

2
@MrLister Thú vị. Làm thế nào mà các tệp lưu trữ cũ của FS giống như AA.BBvới <8 trong phần đầu tiên và <3 trong phần mở rộng? Có phải nó chỉ đệm với không gian?
Kelvin

3
@Kelvin vâng, hai phần được đệm không gian riêng biệt.
cắm vào

12

Tại sao vậy?

Người ta có thể tìm thấy câu trả lời cho " Tại sao lại như vậy? " Trong bài viết về 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)

Giáo dục

Quy tắc khớp ký tự đại diện

  • *Thường khớp với bất kỳ 0 ký tự trở lên, với một ngoại lệ (xem quy tắc tiếp theo). Ký tự đại diện không tham lam có thể tự do kết hợp nhiều hoặc ít ký tự cần thiết cho phần còn lại của mặt nạ để khớp.

  • *.Ở cuối mặt nạ phù hợp với bất kỳ 0 hoặc nhiều ký tự ngoại trừ {dot}. Trong thực tế, quy tắc áp dụng với bất kỳ số lượng ký tự {dot} và {space} nào giữa * và terminal {dot}. Biểu thức chính quy cho thuật ngữ này là"[*][. ]*[.]$"

  • ?Khớp 0 hoặc một ký tự, ngoại trừ {dot}. Lần duy nhất nó khớp với 0 ký tự là khi nó khớp với phần cuối của tên hoặc vị trí trước {dot}. Dấu hỏi cũng có thể được sử dụng nhiều lần để khớp với nhiều hơn một ký tự.

Hàm ý . Các cuối cùng {dot} trong một tập tin / thư mục tên tách tên cơ sở và mở rộng. Vì thế

  • dir *.hiển thị tất cả các mục không có phần mở rộng
  • dir *.*hiển thị tất cả các mục có phần mở rộng bằng 0 hoặc nhiều ký tự .

Nói đúng ra, dir *.hiển thị tất cả các mục không có dấu chấm ( .) . (BTW, Đặt tên tệp, đường dẫn và không gian tên Bài viết MSDN nói rõ ràng rằng " có thể chấp nhận một khoảng thời gian là ký tự đầu tiên của tên ".)

Có cách nào để liệt kê chỉ các tệp có dấu chấm không?

Tôi không nghĩ vậy. Tuy nhiên, có một cách giải quyết với biểu thức chính quy phù hợp.

PowerShell (giải pháp phạm vi đầy đủ nếu được sử dụng trong bảng điều khiển Powershell):

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

Cmd (chỉ một ý tưởng, có thể yêu cầu một số chi tiết):

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

Phụ lục: phần thưởng và giải thích

Một phỏng đoán trực quan Nameđược nối BaseNameExtension không giữ . Kịch bản sau đây chứng minh nó sử dụng cmdPowerShellcác tính năng cốt lõi, và biểu thức chính kỳ lạ ^..*\...*$ bắt nguồn từ kết quả của nó.

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

Đầu ra :

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

So sánh định nghĩa của thuộc BaseNametính, khác nhau cho các tệp và thư mục:

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

Câu trả lời ban đầu của tôi dựa trên sự hiểu lầm không thể tha thứ:

Đọc dir /?, sử dụng 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

Một cách tiếp cận khác: áp dụng findstrregex nhưdir *.* | findstr /V "<.*>"


Điều tôi quan tâm là tại sao lại *.*khớp với tất cả các tệp , như đã nêu trong câu hỏi
phuclv

Tôi sợ gợi ý thay thế của bạn (findstr) không tìm thấy thư mục mà bắt đầu với một .giống .dbus-keyrings, .VirtualBox.vscode.

22
Vì vậy, dir /A:-Dchỉ liệt kê các tập tin được hạnh phúc?
Quentin

4
"Có cách nào để liệt kê chỉ các tệp có dấu chấm không?" dir /A:-Dkhông chính xác 1 / nó liệt kê các tập tin không có phần mở rộng. 2 / nó không liệt kê các thư mục có .tên của họ (hoàn toàn hợp pháp)
DavidPostill

3
ồ ... đã nhiều thập kỷ kể từ lần cuối tôi nhìn thấy "@echo tắt"
rupps

7

Có cách nào để liệt kê chỉ các tệp có dấu chấm không?

Bạn có thể ghép tên tệp với dấu chấm bằng cách sử dụng ký tự đại diện không có giấy tờ <, khớp với chuỗi 0 hoặc nhiều ký tự trong tên cơ sở hoặc chuỗi 0 hoặc nhiều ký tự trong tiện ích mở rộng:

dir "<.<"

Hãy nhớ rằng đó <cũng là một siêu vi khuẩn, vì vậy bạn cần trích dẫn hoặc thoát khỏi nó bất cứ khi nào sử dụng nó trong một mẫu từ vỏ lệnh.


1
Xuất sắc. Ký tự đại diện không có giấy tờ này thực sự tồn tại
phuclv

1

Trình thông dịch dòng lệnh sẽ xem " . " Là "Tất cả tên tệp cơ sở" với "tất cả các phần mở rộng". Một phần mở rộng trống vẫn là một phần mở rộng , vì vậy sẽ được khớp và trả lại với danh sách. Như những người khác đã giải thích, đây là một sự nôn nao từ các phiên bản Windows và MS-DOS trước đó.

Nếu bạn hài lòng khi sử dụng PowerShell, việc tìm các tệp này dễ dàng hơn nhiều. Lưu ý rằng trong PowerShell, "dir" là bí danh cho lệnh ghép ngắn "Get-ChildItem".

Để tìm tất cả các tệp (không phải thư mục / thư mục) có phần mở rộng (ví dụ: "myfile.txt", nhưng không phải "FileWithNoExt"):

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

công tắc "-af" là viết tắt của "-File" chỉ giới hạn các đối tượng trả về cho các tệp. "-ad" sẽ chỉ nhận được thư mục. Các "\." có nghĩa là "một ký tự dấu chấm". Nếu không có dấu gạch chéo ngược, dấu chấm sẽ khớp với bất kỳ ký tự nào, theo regex chuẩn.

Để có được tất cả các tệp có dấu chấm trong tên mà không có phần mở rộng, cũng như phần mở rộng (ví dụ: "myDocument_v1.1.doc" nhưng không phải là "myfile.txt"):

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

Tuy nhiên, lưu ý rằng điều này sẽ loại trừ một tệp có tên như ".archive" với dấu chấm trước. Điều này là do nó được coi là không có tên cơ sở và phần mở rộng của "kho lưu trữ". Nếu bạn muốn bao gồm những điều này:

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

Ở đây, mẫu đối sánh có nội dung "Dấu chấm theo nghĩa đen, HOẶC (|) BeginningOfString (^) theo sau là EndOfString ($) (tức là một chuỗi trống)". Vì một tệp không thể có cả tên cơ sở phần mở rộng trống , nên nó sẽ tìm thấy các tệp bắt đầu bằng dấu chấm.


trong PowerShell ls *.*là đủ, như nhiều người khác đã trả lời trước bạn
phuclv

-2

Nếu bạn gõ lệnh trên, thì đây: * (đây là một thẻ đại diện có nghĩa là bất kỳ chuỗi ký tự nào) theo sau là dấu chấm (.) Theo sau * điều này có thể được hiểu là hiển thị tất cả các tệp có tên như (bất kỳ chuỗi ký tự nào ). (bất kỳ chuỗi ký tự nào) có nghĩa là hiển thị tất cả các tệp với bất kỳ phần mở rộng nào.


1
Vậy thì tại sao lại được Program Filesđưa vào danh sách? Nó không phù hợp với mô hình <sequence of characters>.<sequence of characters>.
gronostaj

Hãy nghĩ về nó nhiều hơn là <Chuỗi từ 0 hoặc nhiều ký tự> Đó là lý do tại sao nó cũng sẽ chọn một tệp có tên ".info" trong đó tên cơ sở trống.
Dave_J
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.