Jak mogę sortować obiekty według trzeciej kolumny w Powershell?

2

Mam taki plik tekstowy:

4108689096 2531 ./ssss/132432.odt
481446057 2293 ./abc/a.txt
3157353085 1096 ./dsjvbjf/c.docx
653380669 1824 ./bcd/x.avi

I chciałbym osiągnąć w programie Powershell sortowanie listy według trzeciej kolumny, ale Sort-Objectwydaje się, że sortuję tę listę według nazwy pliku (według pierwszego znaku po ostatnim /w każdym wierszu), co robię.

Chciałbym osiągnąć coś takiego:

481446057 2293 ./abc/a.txt
653380669 1824 ./bcd/x.avi
3157353085 1096 ./dsjvbjf/c.docx
4108689096 2531 ./ssss/132432.odt

Więc chciałbym, aby posortować według trzeciej kolumny jako ciąg znaków w tym ., /znaków.


Edycja nr 1: jakiś odpowiedni kod

# Gets a relative path based on a base and a full path (to file)
# 
# Usage: RelativePath <path to file> <base path>
# 
# Note: Specifying arguments is mandatory.
function global:RelativePath
{
    param
    (
        [string]$path = $(throw "Missing: path"),
        [string]$basepath = $(throw "Missing: base path")
    )

    return [system.io.path]::GetFullPath($path).SubString([system.io.path]::GetFullPath($basepath).Length + 1)
}

# Calculates CRC checksums for all files in the specified directory and writes
# the checksums to a file
# 
# Usage: CRCSumAll <path to folder to check> <file conatining checksums>
# 
# Note: Specifying arguments is mandatory.
function global:CRCSumAll
{
    param($inputpath,$outputfile)

    $allfiles=get-childitem $inputpath -rec | Where-Object {!($_.psiscontainer)} | Sort-Object Name

    new-item -force -type file $outputfile

    cd $inputpath
    foreach ($file in $allfiles)
    {
        $relfile=RelativePath $file.fullname $inputpath
        $relfile=$relfile -replace("\\","/")
        $relfile="./$relfile"
        cksum.exe $relfile | Out-File -Encoding OEM -Append $outputfile
    }
}

Edycja nr 2: Rozwiązanie

Zrozumiałem, na czym polega problem. Dodałem ścieżki względne po sortowaniu. Prawidłowy kod to:

function global:CRCSumAll
{
    param($inputpath,$outputfile)

    $allfiles=get-childitem $inputpath -rec | Where-Object {!($_.psiscontainer)} #| Sort-Object Name

    new-item -force -type file $outputfile

    cd $inputpath
    foreach ($file in $allfiles)
    {
        $relfile=RelativePath $file.fullname $inputpath
        $relfile=$relfile -replace("\\","/")
        $relfile="./$relfile"
        $relfile | Out-File -Encoding OEM -Append $outputfile
    }

    $sorted=Get-Content $outputfile | Sort-Object
    new-item -force -type file $outputfile
    $sorted | Out-File -Encoding OEM -Append $outputfile

    $forcksum=Get-Content $outputfile
    new-item -force -type file $outputfile
    $forcksum | Foreach-Object { cksum.exe $_ | Out-File -Encoding OEM -Append $outputfile}
}

Teraz muszę tylko trochę wyczyścić kod, ponieważ trzykrotne napisanie pliku jest naprawdę brzydkie. :)

szantaii
źródło
Nie jestem pewien, na czym polega problem. Wziąłem kod, który opublikowałeś, uruchomiłem i uzyskałem posortowany wynik.
EBGreen
Dzięki za pomoc @EBGreen. Chociaż nie jestem pewien, co mam zrobić, zaakceptuj swoją odpowiedź lub napisz odpowiedź na moje własne pytanie, ponieważ bardzo mi pomogłeś i myślę, że zasługujesz na reputację.
szantaii
meh, nie martwię się o przedstawiciela. Moim upodobaniem byłoby, abyś napisał dobre rozwiązanie, dlaczego i dlaczego.
EBGreen
Dobra, więc to zrobię.
szantaii

Odpowiedzi:

2

Wypróbuj coś takiego:

Import-CSV C:\Path\To\File.txt -Header ('foo', 'bar', 'wombat') -delimiter ' ' | Sort-Object wombat

Zostawię moją oryginalną odpowiedź, ponieważ spełnia ona kryteria, o ile dane wejściowe mają dobrze zdefiniowane kolumny. Na podstawie komentarzy rozwiązaniem jest posortowanie tablicy podczas tworzenia:

$allfiles=get-childitem $inputpath -rec | Where-Object {!($_.psiscontainer)} | Sort-Object Name
cd $inputpath
foreach ($file in $allfiles) {cksum.exe $file | Out-File -Append $pathtooutputfile}
EBGreen
źródło
Dzięki. To prawie działa, ale nazwy plików i katalogów, które zawierają spacje, psują sprawę.
szantaii
Więc nie masz odpowiednich kolumn.
EBGreen
Jak dokładnie generujesz plik tekstowy?
EBGreen
Właściwie używam cksum:$allfiles=get-childitem $inputpath -rec | Where-Object {!($_.psiscontainer)} cd $inputpath foreach ($file in $allfiles) {cksum.exe $file | Out-File -Append $pathtooutputfile}
szantaii
Dzięki za edycję, ale tego właśnie używałem. Zredagowałem pytanie i dodałem trochę kodu. W każdym razie dzięki.
szantaii