0

I am trying to write the following script, which checks a folder for a set of files, if they exist, move them to an "archive" folder. If they don't, write an error message to screen and to a log file.

The files move fine, so the first part of the IF is working correctly, but if there are no files to move, the else should kick in and output the error....but it is not.

variables.ps1:

#----- define parameters -----#
#----- Treat All Errors as Terminating -----#
$ErrorActionPreference = "Stop" 
#----- Set count to 0 -----#
$count = 0
#----- get current date ----#
$Now = Get-Date
#----- define amount of days ----#
$Days = "0"
#----- define folder where files are located ----#
$SourceFolder = "C:\HG1\Test\Files"
#----- define folder where files are to be moved to ----#
$DestFolder = "C:\HG1\Test\Files\Archive"
#----- define folder where files are to be moved to ----#
$LogPath = "C:\HG1\archive.log"
#----- define extension ----#
$Extension = "*.log"
#----- define LastWriteTime parameter based on $Days ---#
$LastWrite = $Now.AddDays(-$Days)

#----- get files based on lastwrite filter and specified folder ---#
$Files = Get-Childitem $SourceFolder -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}

archive_files.ps1

#----- Call variables file variables.ps1 - MUST BE IN SAME LOCATION AS SCRIPT ----#
. ./variables.ps1

foreach ($File in $Files)
    {
    if ($File -ne $NULL)
        {
        move-item -path $File.FullName -destination $DestFolder
        Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
        }
    else
        {
        write-host "ERROR: No files to archive" -ForegroundColor "Red"
        Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
        }
    } 
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archiving script completed successfully***")

Any help would be greatly appreciated.

dankellys
  • 43
  • 1
  • 6
  • `$File` will never be null, at least it will be a string. You can check for existing files using `Test-Path`, as shown in this question: http://stackoverflow.com/questions/1732250/check-if-file-exist-and-run-a-batch-file-in-powershell – Gerald Schneider May 18 '16 at 13:10
  • If there are no files in `$Files` then the `foreach` is simply skipped over. The `else` should never run with your code. – Enigmativity May 18 '16 at 13:10
  • Are you wanting to look into all sub folders of `$sourcefolder` and perform an action on those folders based on the presence of .log files? – Matt May 18 '16 at 13:37
  • No, I am just wanting to look for any *.log files in C:\HG1\Test\Files. If any .log files exist, move them to C:\HG1\Test\Files\Archive. If no .log files exist, display that error. I think Test-Path is going to be the answer, just need to have a play around to try and get it working. Sorry, I am a massive N00b when it comes to PowerShell. – dankellys May 18 '16 at 13:42
  • @dankellys - I don't think `Test-Path` is the answer. You're just wanting to see if `$Files` is empty or not, no need to test paths for that. – Enigmativity May 18 '16 at 13:50
  • yes, your right, tried a few variations with test-path, to no avail – dankellys May 18 '16 at 13:52
  • @dankellys - You need to use the `@` notation when replying to someone. – Enigmativity May 18 '16 at 13:55

3 Answers3

0

You should use the Test-Path cmdlet to check whether the file exist:

foreach ($File in $Files)
    {
    if (Test-Path $File)
        {
        move-item -path $File.FullName -destination $DestFolder
        Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
        }
    else
        {
        write-host "ERROR: No files to archive" -ForegroundColor "Red"
        Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
        }
    } 
Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archiving script completed successfully***")
Gerald Schneider
  • 17,416
  • 9
  • 60
  • 78
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • I don't think that this is the intent of the OP's code. I think he wants to test if `$Files` is empty, not if each `$File` exists. – Enigmativity May 18 '16 at 13:12
  • you may be right. Then we need to whole script... Anyway, still want to show him that he can use the `Test-Path` cmdlet to check whether a file exist – Martin Brandl May 18 '16 at 13:13
  • I think that the error message `"ERROR: No files to archive"` is the give away on this one. – Enigmativity May 18 '16 at 13:16
  • Not sure about that. Its possible that he has a text file containing a list of files to delete. In this case My answer will help him. Anyway, we need the whole script. – Martin Brandl May 18 '16 at 13:19
  • Sorry, full script added. I am trying to either archive files if they exist, or error if no files exist. Thanks again. – dankellys May 18 '16 at 13:27
  • 1
    You are using the `Get-ChildItem` cmdlet. This will give you all files from `$SourceFolder` so no iteration will ever give you a path with a file that doesn't exist. – Martin Brandl May 18 '16 at 13:29
0

You've got that logic backwards there.

Each $File in $Files will always be something, but the $Files collection itself may be empty:

if(-not $Files)
{
    foreach($File in $Files)
    {
        Move-Item -Path $File.FullName -Destination $DestFolder
        Add-Content $LogPath -Value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
    }
}
else
{
    Write-Host "ERROR: No files to archive" -ForegroundColor "Red"
    Add-Content $LogPath -Value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
}

Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archiving script completed successfully***")
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Thank you, but Still getting the same issue when there are no *.log files to process. The else is being ignored and the script is just ending after writing "2016-05-18 15:58:21 INFO: ***Archiving script completed successfully***" to the log file. No sign of the "ERROR: No files to archive" message – dankellys May 18 '16 at 15:03
0
#----- Call variables file variables.ps1 - MUST BE IN SAME LOCATION AS SCRIPT ----#
. ./variables.ps1


if ($File)
    {
     foreach ($File in $Files)
     {
        move-item -path $File.FullName -destination $DestFolder
        Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: Archived File $File")
     }

    }
else
    {
    write-host "ERROR: No files to archive" -ForegroundColor "Red"
    Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t ERROR: No files to archive")
    }

Add-Content $LogPath -value ("$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss')) `t INFO: ***Archive script completed successfully***")

here,

  • Foreach each won't process for $null value so include foreach if value is not null
  • if won't enter for $null value so " -ne $null is" not necessary

hopes this works for you,

Regards,

Kvprasoon

Prasoon Karunan V
  • 2,916
  • 2
  • 12
  • 26
  • Excellent, fixed it. Only thing I had to change was `if ($file)` needed to be `if ($files)`. Thank you! – dankellys May 19 '16 at 09:23