Pokaż rozmiary plików czytelne dla człowieka w domyślnym poleceniu ls programu PowerShell

26

Jak mogę zmodyfikować default ls( Get-ChildItem) w PowerShell, aby wyświetlał rozmiary plików czytelne dla człowieka, jak ls -hna komputerze * nix?

ls -lh robi prostą logikę z rozmiarem pliku, dzięki czemu pokazuje bajty dla naprawdę małych plików, kilobajty dla plików powyżej 1 KB (z jednym miejscem dziesiętnym, jeśli jest poniżej 10 KB) i megabajty dla plików powyżej 1 MB (z jednym miejscem dziesiętnym, jeśli jest poniżej 10 MB) .

Tom Mayfield
źródło

Odpowiedzi:

10

Spróbuj tego

PS> gc c:\scripts\type\shrf.ps1xml

<Types>
<Type>
  <Name>System.IO.FileInfo</Name>
   <Members>
      <ScriptProperty>
          <Name>FileSize</Name>
          <GetScriptBlock>
             switch($this.length) {
               { $_ -gt 1tb } 
                      { "{0:n2} TB" -f ($_ / 1tb) }
               { $_ -gt 1gb } 
                      { "{0:n2} GB" -f ($_ / 1gb) }
               { $_ -gt 1mb } 
                      { "{0:n2} MB " -f ($_ / 1mb) }
               { $_ -gt 1kb } 
                      { "{0:n2} KB " -f ($_ / 1Kb) }
               default  
                      { "{0} B " -f $_} 
             }      
          </GetScriptBlock>
     </ScriptProperty>   
  </Members>
</Type>
</Types>

PS> Update-TypeData -AppendPath c:\scripts\type\shrf.ps1xml -verbose
PS> get-childItem $env:windir  | select Name,FileSize,length
PS> # you can paste this in your profile
PS> 

z PS3 możesz także używać danych dynamicznych:

   PS> Update-TypeData -TypeName System.IO.FileInfo -MemberName FileSize -MemberType ScriptProperty -Value { 

    switch($this.length) {
               { $_ -gt 1tb } 
                      { "{0:n2} TB" -f ($_ / 1tb) }
               { $_ -gt 1gb } 
                      { "{0:n2} GB" -f ($_ / 1gb) }
               { $_ -gt 1mb } 
                      { "{0:n2} MB " -f ($_ / 1mb) }
               { $_ -gt 1kb } 
                      { "{0:n2} KB " -f ($_ / 1Kb) }
               default  
                      { "{0} B " -f $_} 
             }      

 } -DefaultDisplayPropertySet Mode,LastWriteTime,FileSize,Name
Walid Toumi
źródło
Bardzo podoba mi się budowanie go jako dodatkowej nieruchomości. Jedyny problem z używaniem wersji PS3 to: Otrzymuję Update-TypeData : Error in TypeData "System.IO.FileInfo": The member DefaultDisplayPropertySet is already present.najnowszą pełną wersję PS3 od 9/4.
Tom Mayfield
3
Świetna odpowiedź! Trudno uwierzyć, że nie ma przełącznika Get-ChildItem, który po prostu zrobiłby to po wyjęciu z pudełka
Ben Collins
Świetna odpowiedź, ale czy ktoś -DefaultDisplayPropertySetmusi pracować?
Nick Cox,
Nie działa jak powiedział @ ThomasG. Mayfield.
ChrisBrownie55
14

Najpierw utwórz następującą funkcję:

Function Format-FileSize() {
    Param ([int]$size)
    If     ($size -gt 1TB) {[string]::Format("{0:0.00} TB", $size / 1TB)}
    ElseIf ($size -gt 1GB) {[string]::Format("{0:0.00} GB", $size / 1GB)}
    ElseIf ($size -gt 1MB) {[string]::Format("{0:0.00} MB", $size / 1MB)}
    ElseIf ($size -gt 1KB) {[string]::Format("{0:0.00} kB", $size / 1KB)}
    ElseIf ($size -gt 0)   {[string]::Format("{0:0.00} B", $size)}
    Else                   {""}
}

Można wtedy rura wyjście Get-ChildItemprzez Select-Objecti używać obliczoną właściwość formatować Wielkość pliku:

Get-ChildItem | Select-Object Name, @{Name="Size";Expression={Format-FileSize($_.Length)}}

Funkcję tę można oczywiście ulepszyć, uwzględniając rozmiary w zakresie PB i więcej, lub w razie potrzeby zmieniać liczbę miejsc dziesiętnych.

Indrek
źródło
Czy istnieje powód, dla którego nie można utworzyć aliasu, aby to zrobić jako sam getshilditem (sprawdź, czy jest flaga -lh czy coś, a jeśli nie, to po prostu użyj Get-ChildItem, w przeciwnym razie użyj tego)
soandos
Nie można tworzyć aliasów dla poleceń potokowych ani zastępować domyślnych aliasów. Jeśli możesz żyć z użyciem takiego aliasu ls2, spróbuj utworzyć inną funkcję wykonującą opisaną logikę na podstawie parametru, a następnie dodaj dla niego alias. Zobacz tutaj, aby uzyskać więcej informacji na temat tworzenia aliasów.
Indrek
Możesz też zajrzeć do niestandardowych plików formatujących, aby rozszerzyć dane wyjściowe polecenia cmdlet. Zobacz ten temat forum jako przykład. Ponadto, aby funkcja formatowania utrzymywała się przez sesje PowerShell, dodaj ją do pliku profilu (sprawdź Get-Variable profilelokalizację).
Indrek
1
Dla mnie ta funkcja nie działa na pliki większe niż ~ 2 GB, zgodnie z $size definicją „an” int, czyli „ a”int32 . Aby to działało z dużymi plikami, zdefiniuj $sizejako int64lub uint64.
Alex Leach
I dostać Select-Object : Es wurde kein Positionsparameter gefunden, der das Argument "System.Collections.Hashtable" akzeptiert.. Jak mogę określić ścieżkę? Używam $pst= Get-ChildItem -Path $home_user -Filter *.pst -Recurse -File| Sort-Object Length -Descending | ForEach-Object{ $_.FullName}. Działa to, ale bez rozmiarów plików.
Timo
6

Coś takiego jak poniżej, aby wymienić tylko rozmiary plików. Tak, to jest trochę obolałe oczy, ale udaje mu się wykonać zadanie.

Aby przekonwertować na KB:

ls | Select-Object Name, @{Name="KiloBytes";Expression={$_.Length / 1KB}}

Do konwersji na MB:

ls | Select-Object Name, @{Name="MegaBytes";Expression={$_.Length / 1MB}}
jmreicha
źródło
1
Najlepsza odpowiedź bez skryptu / funkcji. pipeRozwiązanie!
Timo
3

na podstawie odpowiedzi Walida Toumi:

Kroki do zrobienia:

  • Utwórz własny plik Type za pomocą nowego FileSize-Property
  • Zmień standardowy format wyjściowy dla FileInfo
  • załaduj zmiany w $PROFILE

Utwórz własny plik Type za pomocą nowego FileSize-Property

  • Utwórz własny plik Type: MyTypes.ps1xml
    (wstawiam go $Env:USERPROFILE\Documents\WindowsPowershell, więc tuż obok mojego $PROFILE)

    <?xml version="1.0" encoding="utf-8" ?>
    <Types>
        <Type>
            <Name>System.IO.FileInfo</Name>
            <Members>
                <ScriptProperty>
                    <!-- Filesize converts the length to a human readable
                        format (kb, mb, gb, tb) -->
                    <Name>FileSize</Name>
                    <GetScriptBlock>
                        switch($this.length) {
                            { $_ -gt 1tb } 
                                { "{0:n2} TB" -f ($_ / 1tb) ; break }
                            { $_ -gt 1gb } 
                                { "{0:n2} GB" -f ($_ / 1gb) ; break }
                            { $_ -gt 1mb } 
                                { "{0:n2} MB " -f ($_ / 1mb) ; break }
                            { $_ -gt 1kb } 
                                { "{0:n2} KB " -f ($_ / 1Kb) ; break }
                            default
                                { "{0}  B " -f $_}
                        }
                    </GetScriptBlock>
                </ScriptProperty>
            </Members>
        </Type>
    </Types>
  • załaduj nową właściwość w sesji PowerShell:

    • Update-TypeData -PrependPath $Env:USERPROFILE\Documents\WindowsPowershell\MyTypes.ps1xml
  • wypróbuj nową właściwość
    • Get-ChildItem | Format-Table -Property Name, Length, FileSize

Zmień standardowy format wyjściowy dla FileInfo

  • utwórz własny plik formatu pliku: MyFileFormat.format.ps1xml (ponownie w $Env:USERPROFILE\Documents\WindowsPowershell\)

    <?xml version="1.0" encoding="utf-8" ?> 
    <Configuration>
        <SelectionSets>
            <SelectionSet>
                <Name>FileSystemTypes</Name>
                <Types>
                    <TypeName>System.IO.DirectoryInfo</TypeName>
                    <TypeName>System.IO.FileInfo</TypeName>
                </Types>
            </SelectionSet>
        </SelectionSets>
    
        <!-- ################ GLOBAL CONTROL DEFINITIONS ################ -->
        <Controls>
            <Control>
                <Name>FileSystemTypes-GroupingFormat</Name>
                        <CustomControl>
                            <CustomEntries>
                                <CustomEntry>
                                    <CustomItem>
                                        <Frame>
                                            <LeftIndent>4</LeftIndent>
                                            <CustomItem>
                                                <Text AssemblyName="System.Management.Automation" BaseName="FileSystemProviderStrings" ResourceId="DirectoryDisplayGrouping"/>
                                                <ExpressionBinding>
                                                  <ScriptBlock>
                                                      $_.PSParentPath.Replace("Microsoft.PowerShell.Core\FileSystem::", "")                                                  
                                                  </ScriptBlock>
                                                </ExpressionBinding>
                                                <NewLine/>
                                            </CustomItem> 
                                        </Frame>
                                    </CustomItem>
                                </CustomEntry>
                            </CustomEntries>
                </CustomControl>
            </Control>
        </Controls>
    
        <!-- ################ VIEW DEFINITIONS ################ -->
    
        <ViewDefinitions>
           <View>
                <Name>children</Name>
                <ViewSelectedBy>
                    <SelectionSetName>FileSystemTypes</SelectionSetName>
                </ViewSelectedBy>
                <GroupBy>
                    <PropertyName>PSParentPath</PropertyName> 
                    <CustomControlName>FileSystemTypes-GroupingFormat</CustomControlName>  
                </GroupBy>
                <TableControl>
                    <TableHeaders>
                       <TableColumnHeader>
                          <Label>Mode</Label>
                          <Width>7</Width>
                          <Alignment>left</Alignment>
                       </TableColumnHeader>
                        <TableColumnHeader>
                            <Label>LastWriteTime</Label>
                            <Width>25</Width>
                            <Alignment>right</Alignment>
                        </TableColumnHeader>
                        <TableColumnHeader>
                            <Label>FileSize</Label>
                            <Width>14</Width>
                            <Alignment>right</Alignment>
                        </TableColumnHeader>
                        <TableColumnHeader/>
                    </TableHeaders>
                    <TableRowEntries>
                        <TableRowEntry>
                            <Wrap/>
                            <TableColumnItems>
                                <TableColumnItem>
                                    <PropertyName>Mode</PropertyName>
                                </TableColumnItem>
                                <TableColumnItem>
                                    <ScriptBlock>
                                        [String]::Format("{0,10}  {1,8}", $_.LastWriteTime.ToString("d"), $_.LastWriteTime.ToString("t"))
                                    </ScriptBlock>
                                </TableColumnItem>
                                <TableColumnItem>
                                <PropertyName>FileSize</PropertyName>
                                </TableColumnItem>
                                <TableColumnItem>
                                    <PropertyName>Name</PropertyName>
                                </TableColumnItem>
                            </TableColumnItems>
                        </TableRowEntry>
                    </TableRowEntries>
                </TableControl>
            </View>
            <View>
                <Name>children</Name>
                <ViewSelectedBy>
                    <SelectionSetName>FileSystemTypes</SelectionSetName>
                </ViewSelectedBy>
                <GroupBy>
                    <PropertyName>PSParentPath</PropertyName> 
                    <CustomControlName>FileSystemTypes-GroupingFormat</CustomControlName>  
                </GroupBy>
                <ListControl>
                    <ListEntries>
                        <ListEntry>
                            <EntrySelectedBy>
                                <TypeName>System.IO.FileInfo</TypeName>
                            </EntrySelectedBy>
                            <ListItems>
                                <ListItem>
                                    <PropertyName>Name</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>FileSize</PropertyName>
                                </ListItem>
                               <ListItem>
                                    <PropertyName>CreationTime</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>LastWriteTime</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>LastAccessTime</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>Mode</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>LinkType</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>Target</PropertyName>
                                </ListItem>                        
                                <ListItem>
                                    <PropertyName>VersionInfo</PropertyName>
                                </ListItem>
                            </ListItems>
                        </ListEntry>
                        <ListEntry>
                            <ListItems>
                                <ListItem>
                                    <PropertyName>Name</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>CreationTime</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>LastWriteTime</PropertyName>
                                </ListItem>
                                <ListItem>
                                    <PropertyName>LastAccessTime</PropertyName>
                                </ListItem>
                              <ListItem>
                                <PropertyName>Mode</PropertyName>
                              </ListItem>
                              <ListItem>
                                <PropertyName>LinkType</PropertyName>
                              </ListItem>
                              <ListItem>
                                <PropertyName>Target</PropertyName>
                              </ListItem>
                            </ListItems>
                        </ListEntry>
                    </ListEntries>
                </ListControl>
            </View>
            <View>
                <Name>children</Name>
                <ViewSelectedBy>
                    <SelectionSetName>FileSystemTypes</SelectionSetName>
                </ViewSelectedBy>
                <GroupBy>
                    <PropertyName>PSParentPath</PropertyName> 
                    <CustomControlName>FileSystemTypes-GroupingFormat</CustomControlName>  
                </GroupBy>
                <WideControl>
                    <WideEntries>
                        <WideEntry>
                            <WideItem>
                                <PropertyName>Name</PropertyName>
                            </WideItem>
                        </WideEntry>
                        <WideEntry>
                            <EntrySelectedBy>
                                <TypeName>System.IO.DirectoryInfo</TypeName>
                            </EntrySelectedBy>
                            <WideItem>
                                <PropertyName>Name</PropertyName>
                                <FormatString>[{0}]</FormatString>
                            </WideItem>
                        </WideEntry>
                    </WideEntries>
                </WideControl>
            </View>
            <View>
                <Name>FileSecurityTable</Name>
                <ViewSelectedBy>
                    <TypeName>System.Security.AccessControl.FileSystemSecurity</TypeName>
                </ViewSelectedBy>
                <GroupBy>
                    <PropertyName>PSParentPath</PropertyName> 
                    <CustomControlName>FileSystemTypes-GroupingFormat</CustomControlName>  
                </GroupBy>
                <TableControl>
                    <TableHeaders>
                       <TableColumnHeader>
                          <Label>Path</Label>
                       </TableColumnHeader>
                       <TableColumnHeader />
                       <TableColumnHeader>
                          <Label>Access</Label>
                       </TableColumnHeader>
                    </TableHeaders>
                    <TableRowEntries>
                        <TableRowEntry>
                            <TableColumnItems>
                                <TableColumnItem>
                                    <ScriptBlock>
                                        split-path $_.Path -leaf
                                    </ScriptBlock>
                                </TableColumnItem>
                                <TableColumnItem>
                                <PropertyName>Owner</PropertyName>
                                </TableColumnItem>
                                <TableColumnItem>
                                    <ScriptBlock>
                                        $_.AccessToString
                                    </ScriptBlock>
                                </TableColumnItem>
                            </TableColumnItems>
                        </TableRowEntry>
                    </TableRowEntries>
                </TableControl>
            </View>
           <View>
                <Name>FileSystemStream</Name>
                <ViewSelectedBy>
                    <TypeName>Microsoft.PowerShell.Commands.AlternateStreamData</TypeName>
                </ViewSelectedBy>
                <GroupBy>
                    <PropertyName>Filename</PropertyName> 
                </GroupBy>
                <TableControl>
                    <TableHeaders>
                       <TableColumnHeader>
                          <Width>20</Width>
                          <Alignment>left</Alignment>
                       </TableColumnHeader>
                        <TableColumnHeader>
                            <Width>10</Width>
                            <Alignment>right</Alignment>
                        </TableColumnHeader>
                    </TableHeaders>
                    <TableRowEntries>
                        <TableRowEntry>
                            <TableColumnItems>
                                <TableColumnItem>
                                    <PropertyName>Stream</PropertyName>
                                </TableColumnItem>
                                <TableColumnItem>
                                    <PropertyName>Length</PropertyName>
                                </TableColumnItem>
                            </TableColumnItems>
                        </TableRowEntry>
                    </TableRowEntries>
                </TableControl>
            </View>          
        </ViewDefinitions>
    </Configuration>

    (To allmost bezpośrednią kopią oryginału $PSHOME\FileFormat.format.ps1xml. I tylko zmieniło Lengthsię FileSizekilka razy)

  • załaduj nowy format w naszej sesji PowerShell:

    • Update-FormatData -PrependPath $Env:USERPROFILE\Documents\WindowsPowershell\MyFileFormat.format.ps1xml
  • wypróbuj nową właściwość
    • Get-ChildItem

załaduj zmiany w $PROFILE

  • skopiuj te wiersze, aby $PROFILEzaładować zmiany w każdej nowej sesji

    # local path to use in this script
    $scriptpath = Split-Path -parent $MyInvocation.MyCommand.Definition
    
    # custom types and formats
    # currently only System.IO.FileInfo is changed
    update-TypeData -PrependPath $scriptpath\MyTypes.ps1xml
    update-FormatData -PrependPath $scriptpath\MyFileFormat.format.ps1xml
egolus
źródło
0

Użyłem rozwiązania jmreicha z aliasem w moim profilu $:

function Get-ChildItem-MegaBytes {
  ls $args | Select-Object Name, @{Name="MegaBytes";Expression={$_.Length / 1MB}}
}

Set-Alias -name megs -val Get-ChildItem-MegaBytes

Teraz po prostu piszę: megs [whatever]

Rafael Kitover
źródło