How can I sort objects by third column in Powershell?

2

I've a text file like this:

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

And I'd like to achieve in Powershell to sort the list by the third column, but Sort-Object seems to sort this list by the file name (by the first character after the last / in every row) whatever I do.

I'd like to achieve something like this:

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

So I'd like to sort by the third column as a string including ., / characters.


Edit #1: Some relevant code

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

Edit #2: Solution

I realized what was the problem. I added the relative paths after sorting. So the correct code is:

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

Now I only have to clean up the code a little bit, because writing a file three times is really ugly. :)

szantaii

Posted 2012-04-24T12:54:53.700

Reputation: 123

I'm not sure what the issue is then. I took the code you posted and ran it and got a sorted result. – EBGreen – 2012-04-24T15:04:50.980

Thanks for the help @EBGreen. Though I'm not sure what to do accept your answer or write an answer for my own question, because you helped me a lot, and I think you deserve the reputation. – szantaii – 2012-04-24T16:56:32.793

meh, I'm not worried about the rep. My prefference would be for you to do a nice write up of the solution, the whys and wherefores. – EBGreen – 2012-04-24T17:33:37.127

Okay, I'm going to do that then. – szantaii – 2012-04-25T07:43:53.603

Answers

2

Try something like this:

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

I'll leave my original answer since it meets the criteria as long as the input has well defined columns. Based on the comments, the solution is to sort the array at creation:

$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

Posted 2012-04-24T12:54:53.700

Reputation: 7 834

Thanks. This almost works but file names and directory names that contain space characters messes up the thing. – szantaii – 2012-04-24T13:38:08.507

Then you don't have proper columns. – EBGreen – 2012-04-24T13:39:55.127

How exactly are you generating the text file? – EBGreen – 2012-04-24T13:49:53.537

Actually I use cksum: $allfiles=get-childitem $inputpath -rec | Where-Object {!($_.psiscontainer)} cd $inputpath foreach ($file in $allfiles) {cksum.exe $file | Out-File -Append $pathtooutputfile} – szantaii – 2012-04-24T13:58:43.767

Thanks for the edit, but that's what I've been using. I've edited the question, and added some more code. Anyhow, thanks. – szantaii – 2012-04-24T14:56:05.863