A parameter cannot be found that matches parameter name 'File' - powershell

Power shell script (delete old backup files)
$date = (get-date).AddDays(-10)
$files = Get-ChildItem -Path "\\\sc-sqlbackups\sqlbackups\SA144\Milli\teste" -Files | ?{$_.LastWriteTime -lt $date}
foreach ($file in $files) {
Write-Host "Removing $file"
$file | Remove-Item -ErrorAction SilentlyContinue
}
the above command runs without an issue in Windows powershell(Windows 10). But when I create a SQL Server job with the same command I get the
ERROR
A job step received an error at line 2 in a PowerShell script.
The corresponding line is
'$files = Get-ChildItem -Path "\\sc-sqlbackups\sqlbackups\SA144\Milli\teste" -File | ?{$_.LastWriteTime -lt $date} '. Correct the script and reschedule the job. The error information returned by PowerShell is: 'A parameter cannot be found that matches parameter name 'File'.

-Files is not support in old PS Verisons.
use Where-Object { $_.PSIsContainer -eq $false } Instead!

Related

PowerShell releasing the file lock created by the last criteria test

I need to select images based on size, width, and datemodified, and move them, as well as rename them. Here is my script so far:
Add-Type -Assembly System.Drawing
Get-ChildItem -path C:\temp\images |
Where-Object { $_.Length -ge 250Kb -and $_.lastwritetime -gt (get-date).addDays(-5) -and [Drawing.Image]::FromFile($_.FullName).Width -eq 1920 } |
move-item –PassThru | Rename-Item -NewName {-join #($_.Name,'.jpg')}
The problem is FromFile method is locking the file and preventing the move with this error message:
move-item : The process cannot access the file because it is being
used by another process.
You need to find the other process using the file, with for instance:
$lockedFile = "path/to/locked/file"
$lockingProcessID = Get-Process | foreach {$processVar = $_;$_.Modules `
| foreach {if($_.FileName -eq $lockedFile) {$processVar.id}}}
and then kill the process:
Stop-Process -ID $lockingProcessID -Force
then try again to move your file.

Filter and delete files and folders(and files inside of folders) older than x days in powershell

this is my first post on this forum. Im a beginner in coding and I need help with one of my very first self coded tools.
I made a small script, which deletes files based on if they are older than date x (lastwritetime). Now to my problem: I want the script also to check for files inside of folders inside of a directory and only delete a folder afterwards if it is truly empty. I cant figure out how to solve the recursion in this problem, seems like the script deletes just the entire folder in relation to the date x. Could anyone tell me please what I missed in this code and help me to create a own recursion to solve the problem or fix the code? Thanks to you all, guys! Here is my code:
I would be glad if someone knows how to make the code work by using a function
$path = Read-Host "please enter your path"
"
"
$timedel = Read-Host "Enter days in the past (e.g -12)"
$dateedit = (Get-Date).AddDays($timedel)
"
"
Get-ChildItem $path -File -Recurse | foreach{ if ($_.LastWriteTime -and !$_.LastAccessTimeUtc -le $dateedit) {
Write-Output "older as $timedel days: ($_)" } }
"
"
pause
Get-ChildItem -Path $path -Force -Recurse | Where-Object { $_.PsisContainer -and $_.LastWriteTime -le $dateedit } | Remove-Item -Force -Recurse
""
Write-Output "Files deleted"
param(
[IO.DirectoryInfo]$targetTolder = "d:\tmp",
[DateTime]$dateTimeX = "2020-11-15 00:00:00"
)
Get-ChildItem $targetTolder -Directory -Recurse | Sort-Object {$_.FullName} -Descending | ForEach-Object {
Get-ChildItem $_ -File | Where-Object {$_.LastWriteTime -lt $dateTimeX} | Remove-Item -Force
if ((Get-ChildItem $_).Count -eq 0){Remove-Item $_ -Force}
}
remove -WhatIf after test
To also remove folders that are older than the set days in the past if they are empty leaves you with the problem that as soon as a file is removed from such a folder, the LastWriteTime of the folder is set to that moment in time.
This means you should get a list of older folders first, before you start deleting older files and use that list afterwards to also remove these folders if they are empty.
Also, a minimal check on user input from Read-Host should be done. (i.e. the path must exist and the number of days must be convertable to an integer number. For the latter I chose to simply cast it to [int] because if that fails, the code would generate an execption anyway.
Try something like
$path = Read-Host "please enter your path"
# test the user input
if (-not (Test-Path -Path $path -PathType Container)) {
Write-Error "The path $path does not exist!"
}
else {
$timedel = Read-Host "Enter days in the past (e.g -12)"
# convert to int and make sure it is a negative value
$timedel = -[Math]::Abs([int]$timedel)
$dateedit = (Get-Date).AddDays($timedel).Date # .Date sets this date to midnight (00:00:00)
# get a list of all folders (FullNames only)that have a LastWriteTime older than the set date.
# we check this list later to see if any of the folders are empty and if so, delete them.
$folders = (Get-ChildItem -Path $path -Directory -Recurse | Where-Object { $_.LastWriteTime -le $dateedit }).FullName
# get a list of files to remove
Get-ChildItem -Path $path -File -Recurse | Where-Object { $_.LastWriteTime -le $dateedit} | ForEach-Object {
Write-Host "older as $timedel days: $($_.FullName)"
$_ | Remove-Item -Force -WhatIf # see below about the -WhatIf safety switch
}
# now that old files are gone, test the folder list we got earlier and remove any if empty
$folders | ForEach-Object {
if ((Get-ChildItem -Path $_ -Force).Count -eq 0) {
Write-Host "Deleting empty folder: $_"
$_ | Remove-Item -Force -WhatIf # see below about the -WhatIf safety switch
}
}
Write-Host "All Done!" -ForegroundColor Green
}
The -WhatIf switch used on Remove-Item is there for your own safety. With that, no file or folder is actually deleted, instead in the console it is written what would be deleted. If you are satisfied that this is all good, remove the -WhatIf and run the code again to really delete the files and folders
try something like this:
$timedel=-12
#remove old files
Get-ChildItem "C:\temp" -Recurse -File | Where LastWriteTime -lt (Get-Date).AddDays($timedel) | Remove-Item -Force
#remove directory without file
Get-ChildItem "C:\temp\" -Recurse -Directory | where {(Get-ChildItem $_.FullName -Recurse -File).count -eq 0} | Remove-Item -Force -recurse

Get-childitem is not working with foreach loop

Trying to delete files from multiple path,
So have created a csv file like path,days,filter
importing this file in shell and looping over each object to delete contents, but getchilditem is failing again and again,
Unable to understand reason behind that,
Below is the code what m trying to achieve
Start-Transcript -Path "D:\delete.log"
$pathlist= Import-csv -LiteralPath "D:\diskpath.csv"
$count = 0
foreach($p in $pathlist){
Write-host $p.path " | " $p.days -ForegroundColor DarkCyan
$path = $p.path
$days = $p.days
$filter = $p.filter
Get-ChildItem -Path $path -Filter $filter | where-object{$_.LastWriteTime -lt [datetime]::Now.AddDays(-$days)}|Remove-Item -Force -Verbose -Recurse -ErrorAction SilentlyContinue -Confirm $false
}
Stop-Transcript
without for loop, script executes properly, but with for loop it fails
Please let know if any further information needed on this query,
will like provide the same,
have already google and read multiple questions here at SO, but unable to find reason behind failure,
#T-Me and #Theo
Thanks for highlighting error, haven't looked type error in script my bad, whereas while manual typing in PowerShell was writing correctly, but in script made mistake, now its working-
Start-Transcript -Path "D:\delete.log"
$pathlist= Import-csv -LiteralPath "D:\diskpath.csv"
$count = 0
foreach($p in $pathlist){
Write-host $p.path " | " $p.days -ForegroundColor DarkCyan
$path = $p.path
$days = $p.days
$filter = $p.filter
Get-ChildItem -Path $path -Filter $filter | where-object{$_.LastWriteTime -lt [datetime]::Now.AddDays(-$days)}|Remove-Item -Force -Verbose -Recurse
}

Finding and running a file

I am creating a script where it searches through a bunch of nested folders to find the newest version of a software, which are in .msi form. My code currently can find the file and output it, but is not able to run the file.
I can use Select in the last line for the ForEach to output the correct file but when I change it to Start-Process, I get bombarded by errors.
$path="S:\\Releases\\Program"
$NoOfDirs=Get-ChildItem $path -Directory
ForEach($dir in $NoOfDirs){
Get-ChildItem "$path\$($dir.name)" -File -Recurse |
Where-Object {$_.LastWriteTime -gt ([DateTime]::Now.Adddays(-1))} |
Select-Object #{l='Folder';e={$dir.Name}},Name,LastWriteTime |
Sort-Object -pro LastWriteTime -Descending |
Start-Process -First 1
}
Is there a different command I should be using when running .msi files?
Since your code has to "search through a bunch of nested folders", I'd recommend using the -Recurse switch on Get-ChildItem.
Also use the -Filter parameter to have the search limited to .MSI files.
Something like this:
$path = "S:\Releases\Program"
$refDate = (Get-Date).Adddays(-1)
Get-ChildItem -Path $path -Filter '*.msi' -File -Recurse |
Where-Object {$_.LastWriteTime -gt $refDate} |
ForEach-Object {
# create the arguments for msiexec.exe.
# to find out more switches, open a commandbox and type msiexec /?
$msiArgs = '/i', ('"{0}"' -f $_.FullName), '/qn', '/norestart'
$exitCode = Start-Process 'msiexec.exe' -ArgumentList $msiArgs -NoNewWindow -Wait -PassThru
if ($exitCode -ne 0) {
# something went wrong. see http://www.msierrors.com/tag/msiexec-return-codes/
# to find out what the error was.
Write-Warning "MsiExec.exe returned error code $exitCode"
}
}

Write to the output between two pipeline

I'm trying to write to the output (echo) within two pipe to have a trace of what I'm doing but I have an error.
Get-ChildItem $path -Recurse |
Where-Object { $_.Name -match '.+?\.log\.(\d{4})-(\d{2})-(\d{2})$' -and $_.LastWriteTime -lt $deleteDate } |
Write-Output "deleting file" -PassThru |
Remove-Item
but I have this error :
Write-Output : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
I also tested in the Foreach-Object function
Get-ChildItem $path -Recurse |
Where-Object { $_.Name -match '.+?\.log\.(\d{4})-(\d{2})-(\d{2})$' -and $_.LastWriteTime -lt $deleteDate } |
Foreach-Object {
echo "deleting $($_.Name)";
Remove-Item($_);
}
but here nothing is printed in the console (but the script finish without error and deleted the files I wanted)
So how can I print to thje output wihtin two Pipe ?
Thx
Write-Output sends output to the pipeline. It accepts input via pipeline or argument, but not both, so you can do this:
Write-Output "Test"
or this:
"Test" | Write-Output
but not this:
"Test" | Write-Output "Test"
Solution:
Get-ChildItem $path -Recurse | where {
$_.Name -match '.+?\.log\.(\d{4})-(\d{2})-(\d{2})$' -and $_.LastWriteTime -lt $deleteDate
} | foreach {
# Write-Host writes to the console only
Write-Host "Deleting $($_.Name)"
Remove-Item $_
}
Mind that Remove-Item expects a string argument, so everything you pass will be converted to string. Casting a FileInfo object to string might not always return the full path (because of its implementation of ToString()) depending on how it was created!
In the example above, it is safe to use, but this for instance will throw an an exception (if your current working directory is not $path):
(Get-Item $path).GetFiles() | foreach { Remove-Item $_ }
So it's always safest to use $_.FullName.