ทำไม `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 Todd Wilcox ถูกต้องเกี่ยวกับ DNS โซน DNS หลักจะเรียกว่าแท้จริง.และป้ายกำกับในชื่อ DNS จะถูกคั่นด้วย.(ดังนั้นชื่อของโซน DNS หลักจะเป็นป้ายความยาวศูนย์เดียว) ชายน์หนึ่งของโซน DNS รูท.คือcom.และอีกหนึ่งชายด์com.คือsuperuser.com.และอื่น ๆ
CVn

คำตอบ:


115

ฉันกำลังเขียนคำตอบนี้เพราะ OP ได้เน้นว่า:

สิ่งที่ฉันสนใจคือเหตุผลที่*.*ตรงกับไฟล์ทั้งหมดตามที่ระบุในคำถาม

DIRคำสั่งมาจากเวลาที่:

  1. ไม่อนุญาตให้ใช้เครื่องหมายมหัพภาค (.) เป็นอักขระในชื่อไฟล์หรือโฟลเดอร์
  2. ชื่อไฟล์และโฟลเดอร์ถูก จำกัด ไว้ที่ 8 ตัวอักษรสำหรับชื่อและ 3 ตัวอักษรสำหรับส่วนขยาย

ดังนั้นโดยมาตรฐานที่*.*หมายถึงสิ่งที่ชื่อและสิ่งนามสกุล มันไม่ได้หมายความว่า สตริงที่มี " 'ซึ่งอาจจะหรืออาจจะไม่ได้มีตัวละครก่อนหรือหลัง'." .

นโยบายของ Microsoft กำลังรักษาความเข้ากันได้ย้อนหลัง ดังนั้นการตีความของ*.*จะถูกเก็บไว้

แต่ใน Windows PowerShell *.*หมายถึงสตริงที่มี "." ซึ่งอาจมีหรือไม่มีอักขระอยู่ก่อนหรือหลัง "" .


10
อ่านเพิ่มเติม: blogs.msdn.microsoft.com/oldnewthing/20071217-00/?p=24143
grawity

25
ระบบไฟล์ดั้งเดิมไม่ได้จัดเก็บระยะเวลาไว้ในดิสก์เพียง 11 ตัวเท่านั้นซึ่งเป็นชื่อที่เหลือ
Mr Lister

7
มันเป็นที่น่าสังเกตว่าไฟล์และโฟลเดอร์โดยไม่ต้องนามสกุลยังคงได้รับการรักษาเป็นที่มีส่วนขยายว่างเปล่า ดังนั้นโฟลเดอร์ชื่อ " Folder." และโฟลเดอร์ชื่อ " Folder" จึงมีชื่อเดียวกันกับที่เกี่ยวข้องกับหน้าต่าง
BrainSlugs83

2
@MrLister น่าสนใจ ชื่อไฟล์เก็บของ FS เก่าเหมือนกับAA.BB<8 ในส่วนแรกและ <3 ในส่วนขยายได้อย่างไร มันเป็นแค่ช่องว่าง?
เคลวิน

3
@ เคลวินใช่ทั้งสองส่วนแยกพื้นที่เบาะ
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 ตัวขึ้นไปโดยมีข้อยกเว้นหนึ่งข้อ (ดูกฎต่อไป) wildcard ที่ไม่ใช่โลภมีอิสระในการจับคู่อักขระให้มากหรือน้อยตามที่จำเป็นเพื่อให้ส่วนที่เหลือของหน้ากากจับคู่

  • *.ในตอนท้ายของหน้ากากตรงกับอักขระ 0 ตัวขึ้นไปยกเว้น {dot} ในความเป็นจริงกฎจะใช้กับอักขระ {dot} และ {space} จำนวนเท่าใดก็ได้ระหว่าง * และเทอร์มินัล {dot} การแสดงออกปกติสำหรับคำนี้คือ"[*][. ]*[.]$"

  • ?จับคู่ 0 หรือหนึ่งตัวละครยกเว้นสำหรับ {dot} เวลาเดียวที่ตรงกับ 0 ตัวอักษรคือเมื่อตรงกับส่วนท้ายของชื่อหรือตำแหน่งก่อน {dot} เครื่องหมายคำถามสามารถใช้มากกว่าหนึ่งครั้งเพื่อจับคู่มากกว่าหนึ่งอักขระ

ความหมาย สุดท้าย {} จุดในไฟล์ชื่อโฟลเดอร์ / แยกชื่อและการขยายฐาน ดังนั้น

  • dir *.แสดงรายการทั้งหมดที่ไม่มีส่วนขยายและ
  • dir *.*แสดงรายการทั้งหมดที่มีการขยายตัวของศูนย์หรือมากกว่าตัวอักษร

พูดอย่างเคร่งครัดdir *.แสดงรายการทั้งหมดที่มีระยะเวลาไม่มี ( .) ในชื่อ (BTW, ไฟล์การตั้งชื่อ, เส้นทางและ Namespacesบทความ 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คุณสมบัติหลักและregex แปลก ๆ ^..*\...*$ได้มาจากผลลัพธ์ของมัน

@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

วิธีการอื่น: ใช้findstrregexเป็นdir *.* | findstr /V "<.*>"


สิ่งที่ฉันสนใจคือเหตุผลที่*.*ตรงกับไฟล์ทั้งหมดตามที่ระบุไว้ในคำถาม
phuclv

ผมเกรงว่าข้อเสนอแนะทางเลือกของคุณ (findstr) ไม่พบโฟลเดอร์ที่เริ่มต้นด้วย.เหมือน.dbus-keyrings, และ.VirtualBox .vscode

22
ดังนั้นdir /A:-Dแสดงไฟล์ที่มีความสุขเท่านั้น?
Quentin

4
"มีวิธีใดบ้างที่จะแสดงเฉพาะไฟล์ที่มีจุด?" dir /A:-Dไม่ถูกต้อง 1 / มันแสดงรายการไฟล์ที่ไม่มีนามสกุล 2 / จะไม่แสดงรายการไดเรกทอรีที่มี.ชื่อ (กฎหมายอย่างสมบูรณ์)
DavidPostill

3
อืม ... มันเป็นเวลาหลายสิบปีแล้วที่ฉันเห็น "@echo off" ครั้งล่าสุด
rupps

7

มีวิธีใดบ้างที่จะแสดงเฉพาะไฟล์ที่มีจุด?

คุณสามารถจับคู่ชื่อไฟล์กับจุดโดยใช้ wildcard ที่ไม่มีเอกสาร<ซึ่งจับคู่กับชุดอักขระตั้งแต่ 0 ตัวขึ้นไปในชื่อฐานหรือชุดอักขระ 0 ตัวหรือมากกว่าในส่วนขยาย:

dir "<.<"

จำไว้ว่า<เป็น metacharacter ดังนั้นคุณต้องอ้างหรือหลีกเลี่ยงมันเมื่อใดก็ตามที่ใช้มันในรูปแบบจากเชลล์คำสั่ง


1
ยอดเยี่ยม นี้สัญลักษณ์ตัวแทนที่ไม่มีเอกสารไม่แน่นอนอยู่
phuclv

1

ล่ามบรรทัดคำสั่งจะเห็น " . " เป็น "ชื่อไฟล์ทั้งหมด" พร้อมกับ "นามสกุลทั้งหมด" นามสกุลว่างยังคงเป็นส่วนขยายดังนั้นจะจับคู่และส่งคืนพร้อมกับรายการ อย่างที่คนอื่น ๆ อธิบายนี่เป็นอาการเมาค้างจาก Windows และ MS-DOS รุ่นก่อนหน้า

หากคุณยินดีที่จะดูด้วย PowerShell การค้นหาไฟล์เหล่านี้ง่ายกว่ามาก โปรดทราบว่าใน PowerShell "dir" เป็นนามแฝงสำหรับ "Get-ChildItem" cmdlet

หากต้องการค้นหาไฟล์ทั้งหมด (ไม่ใช่ไดเรกทอรี / โฟลเดอร์) ที่มีนามสกุล (เช่น "myfile.txt" แต่ไม่ใช่ "FileWithNoExt"):

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

สวิตช์ "-af" เป็นแบบย่อสำหรับ "-File" ซึ่ง จำกัด ออบเจกต์ส่งคืนเป็นไฟล์เท่านั้น "-ad" จะได้รับไดเรกทอรีเท่านั้น The "\." หมายถึง "ตัวอักษรจุดตัวอักษร" หากไม่มีแบ็กสแลชจุดจะจับคู่กับอักขระใด ๆ ตาม regex มาตรฐาน

ในการรับไฟล์ทั้งหมดที่มีจุดอยู่ในชื่อโดยไม่มีนามสกุลรวมถึงส่วนขยาย (เช่น "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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.