0

So as the title says, I want to check the LastWriteTime of a specific file (always have same name), and if that file is older than 50 days, i want to delete the content of a folder (which is next to it).

There can be 2 type of paths, here is the structure :

D:\Server\Azerty\BAL\*\CE
D:\Server\WARRIOR\*\Azerty\BAL\*\CE

The "*" is here because there are several folders with different name. The file name I want to check LastWriteTime is "Olympe". The folder which I want to delete the content is named "CE" (see paths above).

I tried a lot of things and I ran out of idea so here I am asking for helps.

Here is my code :

$Folder1 = "D:\Server\Azerty\BAL\*\CE"
$Folder2 = "D:\Server\WARRIOR\*\Azerty\BAL\*\CE"
$pathlogs = "D:\Server\Script\Purge\logs"
$Date = (get-date).ToString("yyyyMMdd-HHmmss")

If((Test-Path $Folder1))
{
    $olympe1 = Get-ChildItem -Path "D:\Server\Azerty\BAL\*\Olympe" 
    $age1 = (Get-Date) - ($olympe1.LastWriteTime)
    if($age1.Days -gt 50) 
    {
        #Logs
        Get-ChildItem -Path $flagcomm1 |
        Where-Object {!$_.PSIsContainer} | Select-Object -Property FullName | Out-File $pathlogs\$Date-Purge.txt -Append
        #Suppression
        Get-ChildItem -Path $Bal1 |
        Where-Object {!$_.PSIsContainer} |
        ForEach-Object {
            Remove-Item -Force -Recurse
        }
    }
}

elseif((Test-Path $Folder2))
{
$olympe2 = Get-ChildItem -Path "D:\Server\WARRIOR\*\Azerty\BAL\*\Olympe"
#$age2 = [datetime](Get-Date).ToUniversalTime() - [datetime]($flagcomm2.LastWriteTime | Select-Object -First 1 | ForEach-Object {$_.ToUniversalTime()})
if($olympe2.LastWriteTime | Select-Object -First 1 |
    ForEach-Object {$_.ToUniversalTime()} -lt (Get-Date).AddDays(-50).ToUniversalTime())
{
    Get-ChildItem -Path $Folder2 -Recurse |
    Where-Object {$_.LastWriteTime.ToUniversalTime() -lt (Get-Date).AddDays(-50).ToUniversalTime()} |
    ForEach-Object {
        Remove-Item -Force -Recurse
    }
}
else {   
}
}

My last tries were on the elseif, since this was my testing case.

With this, I got this error :

ForEach-Object : Cannot bind parameter 'RemainingScripts'. Cannot convert the "-lt" value of type "System.String" to type "System.Management.Automation.ScriptBlock".
At D:\Server\ScriptPurge_ALL - Copy.ps1:34 char:5
+     ForEach-Object {$_.ToUniversalTime()} -lt (Get-Date).AddDays(-50) ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ForEachObjectCommand

I would be glad to get some help :)

PS : Lines and row indicated in the error might be a bit wrong since I changed names for the post.

JosefZ
  • 28,460
  • 5
  • 44
  • 83
  • You are reading from a text file and do not have a DateTime object. Don't use curly brackets and convert string to DateTime, and you need to put in the column name, : ForEach-Object ([System.DateTime]$_.ColumnName) – jdweng Mar 02 '23 at 17:20
  • As an aside: The formatting (indentation) of your code makes it hard to read, and various uninitialized variables are being referenced. Ideally, problems are presented in the form of a [mcve]. – mklement0 Mar 02 '23 at 19:37
  • @jdweng, no files are being read from. All aspects of your comment are irrelevant to this question and therefore a confusing distraction. – mklement0 Mar 02 '23 at 19:43
  • @mklement0 : Then what is this statement doing : Get-ChildItem -Path "D:\Server\Azerty\BAL\*\Olympe" – jdweng Mar 02 '23 at 20:28
  • 1
    @jdweng, it's getting _information about files_ (returns `[System.IO.FileInfo]` instances) - it does not _read_ files. I hope you're aware of the difference between [`Get-ChildItem`](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-childitem) and [`Get-Content`](https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-content). – mklement0 Mar 02 '23 at 20:30

1 Answers1

0

Judging by the description of what you're trying do, you may be looking for something like this (logging code omitted):

$testFileName = 'Olympe'
$siblingFolderName = 'CE'
$paths = 
  'D:\Server\Azerty\BAL\*', 'D:\Server\WARRIOR\*\Azerty\BAL\*' |
  ForEach-Object { Join-Path $_ $testFileName }
$dateThreshold = (Get-Date).Date.ToUniversalTime().AddDays(-50)

Get-ChildItem $paths |
  Where-Object LastWriteTimeUtc -lt $dateThreshold |
  ForEach-Object {
    # Find the path of the sibling folder with name $siblingFolderName
    $targetFolderPath = Join-Path $_.DirectoryName $siblingFolderName
    Get-ChildItem -File $targetFolderPath | Remove-Item -Force -WhatIf
  }

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf and re-execute once you're sure the operation will do what you want.


As for what you tried:

  • The error message indicates a syntax problem with your ForEach-Object call, which was caused by neglecting to enclose the pipeline participating in the if-statement conditional in (...), the grouping operator; here's the corrected syntax, formatted for readability:

    if (
      # Enclose the pipeline in (...), so it can be used as the LHS of
      # the -lt operator.
      (
        $olympe2.LastWriteTime | 
          Select-Object -First 1 | 
          ForEach-Object { $_.ToUniversalTime() }
      ) -lt (Get-Date).AddDays(-50).ToUniversalTime()
    ) { # ...
    
    • As an aside, you could have simplified your conditional as follows, avoiding the need for a nested pipeline:

      if (
        $olympe2.LastWriteTime[0].ToUniversalTime() -lt (Get-Date).AddDays(-50).ToUniversalTime()
      ) { # ...
      
  • The need to enclose pipelines - which includes calls to single commands - in (...) in the context of an expression stems from PowerShell's two fundamental parsing modes, argument mode and expression mode - see this answer for a detailed explanation, as well as the conceptual about_Parsing help topic.

mklement0
  • 382,024
  • 64
  • 607
  • 775