I would add this to my other post, but I can't find it. I have been trying to copy images (JPG and JPEG) from one UNC (source) to two UNCs (destinations) that are three days old. I only need to copy the images, not the folders they are contained in.
I do not get any errors, the email received from the script tells me no images were copied. The destinations do not have any images copied to them and there are images in the source that are newer than three days from todays date. I am completely lost. I have been on Google all day trying to figure this out to no avail so far. Any suggestions would be appreciated.
$ImageLocation = "\\vdifiles\Print-Room\FileSrv\Barcode-Order"
$TestSite = "\\10.0.100.3\www2.varietydistributors.com\catalog\newpictures"
$LiveSite = "\\10.0.100.3\Variety Distributors.com\catalog\newpictures"
$WhenFileWritten = (get-date).AddDays(-3)
$IncludeFileTypes = "*.jpeg,*.jpg"
$LogFile = "C:\Temp\FilesCopied.log"
$EmailServer = "emailserver.me.com"
$EmailFrom = "fromme#me.com"
$AuthUser = "user"
$AuthPass = "pass"
$XHeaderInfo = "X-Header: This email was sent from Laservault."
$EmailTo = "tome#me.com"
$EmailSubject = "Barcode Images Summary."
$EmailBodySent = "Attached to this email is a log file of what images were copied from $ImageLocation to $TestSite and $LiveSite as well as sent to AS2 to send over to Order Stream."
$EmailBodyNotSent = "There were no files in $ImageLocation that matched $WhenFileWritten days old. So, nothing was sent to $TestSite, $LiveSite or AS2."
$TheImages = get-childitem "Microsoft.PowerShell.Core\FileSystem::$ImageLocation" -recurse | where-object {$_.Extension -eq $IncludeFileTypes -and $_.LastWriteTime -gt $WhenFileWritten -and $_.PsIsContainer -eq $false}
foreach ($Images in $TheImages) {
$FileCount = $Images.count
if ($FileCount -gt 0) {
copy-item -path $Images.FullName -destination "Microsoft.PowerShell.Core\FileSystem::$TestSite" -force
copy-item -path $Images.FullName -destination "Microsoft.PowerShell.Core\FileSystem::$LiveSite" -force
write-host "$FileCount files were copied."
write-output $Images >> $LogFile
\\vdifiles\blat$\blat.exe -attach $LogFile -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodySent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
remove-item $LogFile
} else {
\\vdifiles\blat$\blat.exe -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodyNotSent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
}
}
Your original post: Copy-Item : Cannot bind argument to parameter 'Path' because it is null
I copied my answer from there here:
The issue is with the Get-ChildItem not returning anything. It's a small problem because of the -include and -exclude parameters you are feeding into it. You are defining the variable like this:
$IncludeFileTypes = "*.jpeg,*.jpg"
$ExcludeFileTypes = "*.psd,*.tif,*.pdf"
The problem is that the -include and -exclude parameters are expecting a string array (String[]) what you are giving them is a straight string.
We can prove this, if you create a file with the name "a.jpeg,a.jpg", the get-childitem cmdlt will return the file.
The solution is to change your $IncludeFileTypes and $ExcludeFileTypes variables to a string array, and it should return the results that you are expecting:
$IncludeFileTypes = "*.jpeg","*.jpg"
$ExcludeFileTypes = "*.psd","*.tif","*.pdf"
The where-object is not finding any match for any files.
Amend $IncludeFileTypes = "*.jpeg,*.jpg" to $IncludeFileTypes = #("*.jpeg","*.jpg")
Then pass that array of file types into the get-childitem command using the -include Parameter (-filter only takes one filetype, as a string) and remove the $_.Extension check from the where-object command.
e.g.
$TheImages = get-childitem "Microsoft.PowerShell.Core\FileSystem::$ImageLocation" -recurse -include $IncludeFileTypes | where-object {$_.LastWriteTime -gt $WhenFileWritten -and $_.PsIsContainer -eq $false}
You are also checking the count of the wrong variable to get your file count, and it shouldn't be inside the foreach loop.
Get the file count, then if it's greater than zero, iterate through the list if files, copying them.
Try:
$FileCount = $TheImages.count
if ($FileCount -gt 0) {
foreach ($Images in $TheImages) {
And also
write-output $TheImages >> $LogFile
Instead of
write-output $Images >> $LogFile
You are declaring the list wrong, it should be like this:
$IncludeFileTypes = #("*.jpeg","*.jpg")
Try searching with the -Include like this:
$TheImages = get-childitem "Microsoft.PowerShell.Core\FileSystem::$ImageLocation" -recurse -Include $IncludeFileTypes | where-object {$_.LastWriteTime -gt $WhenFileWritten -and $_.PsIsContainer -eq $false}
And check if the variable is empty after that:
if($TheImages -ne $null)
{
#move...
#send email...
#etc
}
Hope this solves your issue.
Related
I have created a script that compress files older than N days using PowerShell.
Like this:
param (
$dirPath, `
[int] $daysAgo, `
$logOutput=$dirPath+"\old_reports.log", `
$fileExt
)
$curDate = Get-Date
$timeAgo = ($curDate).AddDays($daysAgo)
$files = Get-ChildItem -Recurse `
-Path $dirPath `
-Include *.$fileExt| `
Where-Object { $_.LastWriteTime -lt $timeAgo } | `
Select -ExpandProperty FullName
& 'C:\Program Files\7-Zip\7Z.exe' a -t7z -mx9 old_reports.7z $files -bb1 -sdel
echo $files > $logOutput
It is working, but, since there are many files, it takes a while to fill the $files variable. While it is doing that, the prompt shows only a blinking cursor. Therefore, I am not aware if the script is actually doing something or it's paused by an accidental click.
Is there a way to show that $files variable is receiving input?
Without restructuring your command - and thereby sacrificing performance - I see only one option:
In addition to capturing file-info objects in variable $files, print them to the display as well, which you can do with the help of the common -OutVariable parameter:
# Output the files of interest *and* capture them in
# variable $files, via -OutVariable
Get-ChildItem -Recurse `
-Path $dirPath `
-Include *.$fileExt| `
Where-Object { $_.LastWriteTime -lt $timeAgo } | `
Select -ExpandProperty FullName -OutVariable files
I have a question that I hope one of you can help me with.
The following script does its job, it sends the email of the folders that are older than 30 days.
I want to add 2 more features...
If the OwnerEmail.txt is not there or empty.. it will not send the email.
If there are not folders older than 30 days, it will not send the email.
I am just having problems using the CONTINUE feature to skip the ForEach
$ParentFolders = Get-ChildItem -Path "C:\Test\WRA" -Directory |
Select-Object -ExpandProperty FullName
foreach ($SubFolder in $ParentFolders) {
$Contact = Get-Content -Path ($SubFolder + "\OwnerEmail.txt")
$emailTime = (Get-Date).ToString("MM/dd/yyyy")
$WRAHTMLReport = Get-ChildItem -Path $SubFolder -Directory |
Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-30))} |
Select-Object Name, CreationTime |
ConvertTo-Html -Head $Header -PreContent "
<h2>Current Nuix Case(s)</h2>
<body>
Report was sent on $emailTime
<br></br>
When you have a moment can you please confirm if any of these cases can be removed from Nuix:
<body>
<br></br> " |
$WRAHTMLReport = $WRAHTMLReport -join ""
Start-Sleep -s 2
Send-MailMessage -SmtpServer mail.company.com -to $Contact -from cubam1#company.com -Subject "Nuix Cases" -Body $WRAHTMLReport -BodyAsHtml
}
So, it could look something like this, note that I'm only showing the relevant parts of the code.
I think in this case, is safe to put the $emailTime outside the loop since you're only gathering the date in MM/dd/yyyy format and, I also added the $folderLimitDate outside the loop.
This variable contains the HTML body
$mailBody = ConvertTo-Html -InputObject $WRAHTMLReport... so remember to change the -Body $mailBody on Send-MailMessage
$emailTime = (Get-Date).ToString("MM/dd/yyyy")
$folderLimitDate = (Get-Date).AddDays(-30)
foreach ($SubFolder in $ParentFolders)
{
$path = Join-Path $SubFolder -ChildPath 'OwnerEmail.txt'
# If OwnerEmail.txt doesn't exist on this path,
# go to next loop iteration
if(-not(Test-Path $path)){ continue }
$Contact = Get-Content $path
$WRAHTMLReport = Get-ChildItem -Path $SubFolder -Directory |
Where-Object LastWriteTime -LT $folderLimitDate |
Select-Object Name, CreationTime
# If this variable is null, go to next loop iteration
if(-not $WRAHTMLReport){ continue }
[string]$mailBody = ConvertTo-Html -InputObject $WRAHTMLReport...
...
...
...
I have tried with powershell to check if files in a directory with subfolders do not have a changeover time of 10 hours (LastWriteTime).
If this is the case I would like to log its name and directory in a log.txt file and have an email alert.
So I did that, but it does not really work well ... below any help is appreciated!
$directories ='C:\folders'
$Logfile = "C:\log.txt"
function logit($msg){
$msg='[{0}]{1}' -f [datetime]::Now, $msg
$msg|Out-File $logfile -append
}
if([datetime]::Now - (Get-Item $directories).LastWriteTime -gt
[timespan]'0:10:0:0'){
Send-MailMessage -to "name <name#domain.com>" -from "name
<name#domain.com>" -subject "object" -smtpserver "smtp.domain.com" ..
Out-File $Logfile
Write-Host
}
Thank you
I try this, i get the good result. i'ts possible to modify "comparedate" in hours ?
$compareDate = (Get-Date).AddDays(-1)
#(Get-ChildItem -Path C:\temp\*.* -Filter '*.*' -Recurse | Where-Object {
$_.LastWriteTime -gt $compareDate})
try this:
$compareDate = (Get-Date).AddHours(-10)
Get-ChildItem "C:\temp\" -Recurse -file | Where LastWriteTime -gt $compareDate
I'm trying to get this script to do a subdirectory compare based on filename and then only files that are 30 days or younger. The Syntax seems to acceptable but the HandbrakeCLI encoding doesn't launch.
Clear screen
$SourceDir = "\\netshare\testing\Source\*.MP4"
$DestinationDir = "\\netshare\testing\Completed_mp4\*.MP4"
$s1 = get-childitem -path $SourceDir -Recurse -Force | Where-Object {$_.LastWriteTime -gt (Get-Date).addDays(-30)}
$d1 = get-childitem -path $DestinationDir -Recurse
$results = #(compare-object $s1 $d1) | Where-Object {$_.Name -ne $_.Name}
$quantity = $results | measure
$Filecount = $quantity
$Process = 0;
foreach ($result in $results){
Write-Host -----------------------------------------------------------------
Write-Host Handbrake Batch Encoding
$Process++;
$results = $file.DirectoryName + "\" + $file.BaseName + ".MP4";
$progress = ($Process / $filecount) * 100
$progress = [Math]::Round($progress,2)
#Clear-Host
Write-Host "Processing - $results"
Write-Host "File $Process of $Filecount - $progress%"
Write-Host -------------------------------------------------------------------------------
$s1 = get-childitem -path $SourceDir -Recurse -Force | Where-Object {$_.LastWriteTime -gt (Get-Date).addDays(-30)}
$d1 = get-childitem -path $DestinationDir -Recurse
Start-Process "C:\Users\Downloads\HandBrakeCLI-1.0.1-win-x86_64.exe -ArgumentList -q 25 -i '$results' -o '$d1'"
}
$results = #(compare-object $s1 $d1) | Where-Object {$_.Name -ne $_.Name}
would be a good start to look. This will not return any results unless $_.Name is NaN (which is unlikely).
Once you fixed that there should be an error message that
C:\Users\Downloads\HandBrakeCLI-1.0.1-win-x86_64.exe -ArgumentList -q 25 -i '$results' -o '$d1'
cannot be run.
Note that you use quotation marks around the whole line, effectively telling Start-Process that the whole thing is the program to run. Which it isn't.
There's no need for Start-Process here anyway, though, you should be able to just use
C:\Users\Downloads\HandBrakeCLI-1.0.1-win-x86_64.exe -q 25 -i $results -o $d1
(Note also that due to your use of single quotes, you were passing $results and $d1 verbatim to the program instead of the variable contents. Furthermore I'm fairly sure you'd need commas between arguments with -ArgumentList instead of spaces, as that would be normal PowerShell parameter binding behaviour.)
There are a bunch of other mistakes here:
Clear screen can just be clear, cls, or Clear-Host. The screen does nothing.
$quantity = $results | measure should probably be $quantity = ($results | measure).Count or simply #($results).Count. Otherwise you won't get the output you want a few lines later.
I am not sure what is going on. I am very new to Power Shell.
I have a folder structure containing images in them. I am looking to get all the images that are X days old and copy those images to two other locations. The error I am getting is:
Copy-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\Documents and Settings\Administrator.VDICORP\Desktop\ProcessOSImages.ps1:37 char:24
+ copy-item -path <<<< $TheImage -destination $TestSite
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand
My code is as follows:
$TodaysDate = get-date
$FileAgeInDays = "-2"
$ImageLocation = "\\vdifiles\Print-Room\FileSrv\Barcode-Order"
$TestSite = "\\10.0.100.3\www2.varietydistributors.com\catalog\newpictures"
$LiveSite = "\\10.0.100.3\Variety Distributors.com\catalog\newpictures"
$WhenFileWritten = $TodaysDate.AddDays($FileAgeInDays)
$IncludeFileTypes = "*.jpeg,*.jpg"
$ExcludeFileTypes = "*.psd,*.tif,*.pdf"
$LogFile = "C:\Temp\FilesCopied.log"
$EmailServer = "mx1.domain.com"
$EmailFrom = "alerts#domain.com"
$AuthUser = "user"
$AuthPass = "pass"
$XHeaderInfo = "X-Header: This email was sent from Laservault."
$EmailTo = "me#domain.com"
$EmailSubject = "Barcode Images Summary."
$EmailBodySent = "TEST Attached to this email is a log file of what images were copied from $ImageLocation to $TestSite and $LiveSite as well as sent to AS2 to send over to Order Stream."
$EmailBodyNotSent = "TEST There were no files in $ImageLocation that matched $WhenFileWritten days old. So, nothing was sent to $TestSite, $LiveSite or AS2."
$TheImages = get-childitem $ImageLocation -include $IncludeFileTypes -exclude $ExcludeFileTypes -recurse -force | where-object {$_.CreationTime -le "$WhenFileWritten" -and $_.PsIsContainer -ne $true}
foreach ($TheImages in $TheImage) {
$FileCount = ($TheImage).count
if (!($FileCount -eq 0)) {
copy-item -path $TheImage -destination $TestSite
copy-item -path $TheImage -destination $LiveSite
write-host $FilesCount "images were copied."
write-output $TheImage >> $LogFile
\\vdifiles\blat$\blat.exe -attach $LogFile -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodySent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
remove-item $LogFile
} else {
\\vdifiles\blat$\blat.exe -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodyNotSent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
}
}
Where am I going wrong?
It's a simple problem. You flipped your variables in your foreach statement. You have:
foreach ($TheImages in $TheImage) {
You should have:
foreach ($TheImage in $TheImages) {
--- Edit
The other issue is with the Get-ChildItem not returning anything. It's a small problem because of the -include and -exclude parameters you are feeding into it. You are defining the variable like this:
$IncludeFileTypes = "*.jpeg,*.jpg"
$ExcludeFileTypes = "*.psd,*.tif,*.pdf"
The problem is that the -include and -exclude parameters are expecting a string array (String[]) what you are giving them is a straight string.
We can prove this, if you create a file with the name "a.jpeg,a.jpg", the get-childitem cmdlt will return the file.
The solution is to change your $IncludeFileTypes and $ExcludeFileTypes variables to a string array, and it should return the results that you are expecting:
$IncludeFileTypes = "*.jpeg","*.jpg"
$ExcludeFileTypes = "*.psd","*.tif","*.pdf"