1

I'm writing a function to take a series of video files and sort them based on their file dates. Here is the get-child loop:

$TransitFolder = "D:\Stuff\Pictures\Transit"

function New-Dir {
    param(
        [string] $Path
    )
    if (!(Test-Path -Path $Path)) {
        Write-Host "Creating: >$Path<"
        New-Item -Path $Path -ItemType Directory
    }
    else {
        #Write-Host "Path exists: >$Path<";
    }
}


function Get-DateFolder {
    param (
        [string] $Name
    )

    $FileName = $Name.Split('_')[0]
    $Which = if ($Name.Split('.')[1] -eq "jpg") {"pics"} else {"vids"}

    $FileDate = [datetime]::ParseExact($FileName,'yyyyMMdd',$null)
    $DestFolder = (Join-Path $TransitFolder $Which)
    $YearFolder = (Join-Path $DestFolder $FileDate.Year)
    $MonthFolder = (Join-Path $YearFolder ('{0} - ({1}) {2}' -f $FileDate.Year,([string]$FileDate.Month).PadLeft(2,'0'),$FileDate.ToString("MMMM")))
    Write-Host "Making new month folder '$MonthFolder'"
    New-Dir -Path $MonthFolder  
    Write-Host "Returning month folder '$MonthFolder'"
    return $MonthFolder
}

function Count-Existing {
    param(
        [string] $Path,
        [string] $NewName
    )
    #somehow this is creating a "path path" folder? WTF?
    #New-Dir $Path

    # Newname has no extension so this will be every thng with the same YYYYMMDD_HHMMSS
    $Results = Get-ChildItem -Path "$Path\*" -Include "$NewName*" | Group-Object -NoElement
    return $Results.Length
}


    Get-ChildItem -Path "$TransitFolder\*" -Include *.mp4 | ForEach {

        # This part not necessary, but for readability
        [string]$OldName = $_.Name.Split('.')[0]
        [string]$Ext = '.'+$_.Name.Split('.')[1]
        [string]$NewName = [string]$_.LastWriteTime.ToString('yyyyMMdd_hhmmss')

        #Determine Target Folder from filename date pattern. Extension determines if it's "pics" or "vids" 
        Write-Host "before getdatefolder target folder for vid '$TargetFolder'"
        $TargetFolder = Get-DateFolder ($NewName+$Ext)
        Write-Host "after getdatefolder target folder for vid '$TargetFolder'"
        $DestCount = Count-Existing $TargetFolder "$NewName$Ext"
        
        #Test for collision - Target folder is king. If there are already some there, count continues from there
        if ($DestCount){
            $NewName = $NewName+'_'+([string]$DestCount).PadLeft(3,'0')
        }

        # Move the file to the new folder so when we rename it, it doesn't have collision problems with the ones in the current folder
        If (Test-Path -Path "$TransitFolder\$OldName$Ext" ) {
            #Move-Item "$TransitFolder\$OldName$Ext"  "$TargetFolder\$NewName$Ext"
            Write-Host "$TransitFolder\$OldName$Ext => $TargetFolder\$NewName$Ext"
        }
    }

In the console output, I can see that it's making the folder correctly and returning the correct value as well:

before getdatefolder target folder for vid 'D:\Stuff\Pictures\Transit\vids\2018\2018 - (12) December'
Making new month folder 'D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January'
Creating: >D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January<
Returning month folder 'D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January'

Everything's fine so far. But the moment it returns to the Get-ChildItem foreach loop, the very next line after the Get-DateFolder call writes to host the value and suddenly it's repeated somehow and throws an error:

after getdatefolder target folder for vid 'D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January'
Get-ChildItem : Cannot find path 'D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January D:\Stuff\Pictures\Transit\vids\2019\2019 - (01) January' because it does not exist.
At C:\stuff\Working\htdocs\PSSort\sorter.ps1:95 char:13
+ ...  $Results = Get-ChildItem -Path "$Path\*" -Include "$NewName*" | Grou ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (D:\Stuff\Pictur... - (01) January:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

How is "return X" somehow resulting in "XX" in this code?

not_a_generic_user
  • 1,906
  • 2
  • 19
  • 34
  • Unclear where `$Results = Get-ChildItem -Path "$Path\*"...` is in your code but its pretty clear that `$Path` is an array having a duplicated value – Santiago Squarzon Jul 04 '23 at 19:46
  • 1
    In short: any output - be it from a PowerShell command, an operator-based expression, or a .NET method call - that is neither captured in a variable nor redirected (sent to a file or via the pipeline to another command) is _implicitly output_ from a script or function. To simply _discard_ such output, use `$null = ...`. If you don't discard such output, it becomes part of a script or function's "return value" (stream of output objects). See the linked duplicate for more information. – mklement0 Jul 04 '23 at 19:48
  • 1
    In your case, it is the `New-Dir` call whose output isn't captured or suppressed, and therefore becomes part of the `Get-DateFolder` function's "return value" (stream of output objects). – mklement0 Jul 04 '23 at 19:49
  • It's already been marked duplicate, but if you put it as an answer, I'll accept it. That seems to have been the problem. I suspected it was some default behavior of PS that I didn't know about. Forcing it to null so I can keep track of what's returned seems to ahve been the answer. – not_a_generic_user Jul 04 '23 at 19:51
  • 1
    , but I think it's sufficient to link to the duplicate, which (hopefully) has all angles covered (it shows the `$null = ...` technique`). – mklement0 Jul 04 '23 at 20:41

0 Answers0