Powershell - include Get-Date in .log file inside the Add-Content Cmdlet - powershell

I've made a small Powershell Script which deletes alle files and folders except specific ones.
The script itself works pretty good but I have a lot of troubble getting the logging to work. I'm currently on a good way with the Add-Content Cmdlet which works good. The only thing I now want to include is a small Get-Date Cmdlet inside the Add-Content which also includes the current time in the log when the specific file/folder was deleted. But I just can't get it to work properly. Can someone help me?
Here is what I got so far:
Get-ChildItem -Path 'C:\sample\*\notesdata' -Recurse -exclude names.nsf |
Select -ExpandProperty FullName |
Where {$_ -notlike 'C:\sample\*\notesdata\Roaming*'} |
Where {$_ -notlike 'C:\sample\*\notesdata\Archive*'} |
sort length -Descending |
Remove-Item -force -Recurse -Verbose 4>&1 | Add-Content -Path .\ergebnis.log, .\ergebnis2.log -Value (Get-Date)
The file "names.nsf" and the folders "Roaming", "Archive" will not get deleted.
Thanks for your help :)

Agree with #Olaf I'm guessing you're getting error like:
Add-Content : 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.
If you want to date the output for logging purposes you could add something a ForEach-Object before the Add-Content command. Something like:
Remove-Item C:\temp\something.txt -Verbose 4>&1 | ForEach-Object{ "$(Get-Date -format g) : $($_)" } | Add-Content C:\temp\something2.txt
Let us know if that helps. Thanks.

Related

Deleting folders from GridView output

I've been working with several scripts found on here and other sources trying to work up a PowerShell script to delete thousands of empty folders that end up on our system from daily forms processing. There's several simple and effective ways of doing it, but I need a way to verify and select the folders so I don't delete the handful of folders that shouldn't be deleted even when empty.
I'm using a parameter statement for $folder so I can either input it on the command line or it will prompt for it. Using this command I get the gridview and if I simply echo the output it's fine. However, I can't seem to figure out how to pass the output to either Remove-Item or Del -Recurse. Using Del gives me:
del : Cannot find drive. A drive with the name '#{FullName=D' does not exist."
which seems that it's either not getting the output vs echo or it's looking for an array?
foreach ($folder in (dir $target -Directory -Recurse |
where {-not $_.GetFiles("*", "AllDirectories")} |
Select Fullname |
Out-GridView -PassThru -Title "Select Folders For Deletion and Click OK"
)) {
del $folder -Recurse -WhatIf
}
I suspect this will accomplish what you want. There's no need for a ForEach loop here where you're already working with a pipeline.
Get-ChildItem -LiteralPath $Target -Directory -Recurse -Force |
Where-Object { !$_.GetFiles('*','AllDirectories') } |
Select-Object -Property 'FullName' |
Out-GridView -PassThru -Title 'Select folders for deletion and click OK' |
ForEach-Object { Remove-Item -LiteralPath $_.FullName -WhatIf }

Powershell: Recursively search a drive or directory for a file type in a specific time frame of creation

I am trying to incorporate Powershell into my everyday workflow so I can move up from a Desktop Support guy to a Systems Admin. One question that I encountered when helping a coworker was how to search for a lost or forgotten file saved in an unknown directory. The pipeline I came up with was:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Out-File pdfs.txt
This code performed exactly how I wanted but now I want to extend this command and make it more efficient. Especially since my company has clients with very messy file management.
What I want to do with this pipeline:
Recursively search for a specific file-type that was created in a specified time-frame. Lets say the oldest file allowed in this search is a file from two days ago.
Save the file to a text file with the columns containing the Filename, FullName(Path), and sorted by the created time in descending order.
What I have so far:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Select-Object Name, FullName | Out-File *pdfs.txt
I really need help on how to create a filter for the time that the file was created. I think I need to use the Where-Object cmdlet right after the dir pipe and before the Select Object pipe but I don't know how to set that up. This is what I wrote: Where-Object {$_.CreationTime <
You're on the right track, to get the files from a specific file creation date range, you can pipe the dir command results to:
Where-Object {$_.CreationTime -ge "06/20/2017" -and $_.CreationTime -le "06/22/2017"}
If you want something more repeatable where you don't have to hard-code the dates everytime and just want to search for files from up to 2 days ago you can set variables:
$today = (Get-Date)
$daysago = (Get-Date).AddDays(-2)
then plugin the variables:
Where-Object {$_.CreationTime -ge $daysago -and $_.CreationTime -le $today}
I'm not near my Windows PC to test this but I think it should work!
See if this helps
dir c:\ -Recurse -Filter *.ps1 -ErrorAction SilentlyContinue -Force | select LastWriteTime,Name | Where-Object {$_.LastWriteTime -ge [DateTime]::Now.AddDays(-2) } | Out-File Temp.txt

Powershell where filter not working

I have the following simple code:
remove-item -path $path | where($_ -like "*IE*")
But for some reason I get an error due to the wildcards
Your script above has a few errors. I'll try to help you out with them.
First and foremost, the Remove-Item cmdlet doesn't provide any output for your where line. You've got to get it first. I'm going to assume since you want to filter out items that don't match IE, you're getting multiple files from a directory. If this is only a single file, all you need to do is Remove-Item -Path $Path. If it's a directory, the cmdlet is Get-ChildItem
Get-ChildItem -Path $Path
Now that you have all of your items from $Path, we need to filter them. You do this with Where-Object. Like this...
Get-ChildItem -Path $Path | Where-Object
This is where the next issue comes in. You are using -like when I think you want -match. Also, your $_ is going to signify the entire object. We need to match a property of the object. It'd look like this
Get-ChildItem -Path $Path | Where-Object -FilterScript { $_.PROPERTYNAME -match "IE"}
Now that we have our objects, and we have them sorted, it's time to remove them. We do this using the Remove-Item cmdlet, from above. Please notice that this time, it's at the end of the pipeline, rather than the beginning.
Get-ChildItem -Path $Path | Where-Object -FilterScript { $_.PROPERTYNAME -match "IE"} | Remove-Item
If you don't want to confirm each and every one (and you're sure these are the items you want to remove), add -Confirm:$false after Remove-Item. Otherwise, you'll have to confirm in the console every file you want to remove.
I really hope this helps!

Outputing Remove-Item to a log file

Scanning a directory for a specific set of files and sorting them by date. Keeping 7 of the LATEST copies of the file regardless of date, and removing the oldest if over 7. I am having a hard time producing a log file showing the deletes since Remove-Item has no output.
Below is a copy of my code:
$path = "C:\- Deploy to Production -\Previous Deploys\*_*_BOAWeb.rar" #BOA
$files = Get-ChildItem -Path $path -Recurse | Where-Object {-not $_.PsIsContainer}
$keep = 7
if ($files.Count -gt $keep) {
$files | Sort-Object CreationTime |
Select-Object -First ($files.Count - $keep) |
Remove-Item -Force
}
First off you are over complicating things. Add -Descending to your Sort command, and then change your Select to -Skip $keep. It's simpler that way. Then you have options for outputting your deleted files.
Remove-Item -Force -Verbose 4>&1 | Add-Content C:\Path\To\DeletedFiles.log
or (keeping with your current code above)
Select-Object -First ($files.Count - $keep) |Tee-Object -filepath C:\Path\To\DeletedFiles.log -append
The first will output the verbose output of Delete-Item and append it to whatever log file you specify the path for (use Set-Content if you want to replace the log instead). The second option will append the [FileInfo] objects onto a log that you specify.
Edit: As pointed out by Ansgar Wiechers, I had forgotten to to combine my verbose and stdout streams, so 4>&1 was added to the above code to correct that issue.

Delete files containing string

How can I delete all files in a directory that contain a string using powershell?
I've tried something like
$list = get-childitem *.milk | select-string -pattern "fRating=2" | Format-Table Path
$list | foreach { rm $_.Path }
And that worked for some files but did not remove everything. I've tried other various things but nothing is working.
I can easily get the list of file names and can create an array with the path's only using
$lista = #(); foreach ($f in $list) { $lista += $f.Path; }
but can't seem to get any command (del, rm, or Remove-Item) to do anything. Just returns immediately without deleting the files or giving errors.
Thanks
First we can simplify your code as:
Get-ChildItem "*.milk" | Select-String -Pattern "fRating=2" | Select-Object -ExcludeProperty path | Remove-Item -Force -Confirm
The lack of action and errors might be addressable by one of two things. The Force parameter which:
Allows the cmdlet to remove items that cannot otherwise be changed,
such as hidden or read-only files or read-only aliases or variables.
I would aslo suggest that you run this script as administrator. Depending where these files are located you might not have permissions. If this is not the case or does not work please include the error you are getting.
Im going to guess the error is:
remove-item : Cannot remove item C:\temp\somefile.txt: The process cannot access the file 'C:\temp\somefile.txt'
because it is being used by another process.
Update
In testing, I was also getting a similar error. Upon research it looks like the Select-String cmd-let was holding onto the file preventing its deletion. Assumption based on i have never seen Get-ChildItem do this before. The solution in that case would be encase the first part of this in parentheses as a sub expression so it would process all the files before going through the pipe.
(Get-ChildItem | Select-String -Pattern "tes" | Select-Object -ExpandProperty path) | Remove-Item -Force -Confirm
Remove -Confirm if deemed required. It exists as a precaution so that you don't open up a new powershell in c:\windows\system32 and copy paste a remove-item cmdlet in there.
Another Update
[ and ] are wildcard searches in powershell in order to escape those in some cmdlets you use -Literalpath. Also Select-String can return multiple hits in files so we should use -Unique
(Get-ChildItem *.milk | Select-String -Pattern "fRating=2" | Select-Object -ExpandProperty path -Unique) | ForEach-Object{Remove-Item -Force -LiteralPath $_}
Why do you use select-string -pattern "fRating=2"? You would like to select all files with this name?
I think the Format-Table Path don't work. The command Get-ChildItem don't have a property called "Path".
Work this snipped for you?
$list = get-childitem *.milk | Where-Object -FilterScript {$_.Name -match "fRating=2"}
$list | foreach { rm $_.FullName }
The following code gets all files of type *.milk and puts them in $listA, then uses that list to get all the files that contain the string fRating=[01] and stores them in $listB. The files in $listB are deleted and then the number of files deleted versus the number of files that contained the match is displayed(they should be equal).
sv -name listA -value (Get-ChildItem *.milk); sv -name listB -value ($listA | Select-String -Pattern "fRating=[01]"); (($listB | Select-Object -ExpandProperty path) | ForEach-Object {Remove-Item -Force -LiteralPath $_}); (sv -name FCount -value ((Get-ChildItem *.milk).Count)); Write-Host -NoNewline Files Deleted ($listA.Count - $FCount)/($listB.Count)`n;
No need to complicate things:
1. $sourcePath = "\\path\to\the\file\"
2. Remove-Item "$sourcePath*whatever*"
I tried the answer, unfortunately, errors seems to always come up, however, I managed to create a solution to get this done:
Without using Get-ChilItem; You can use select-string directly to search for files matching a certain string, yes, this will return the filename:count:content ... etc, but, internally these have names that you can chose or omit, the one you need is the "filename" to do this pipe this into "select-object" choosing the "FileName" from the output.
So, to select all *.MSG files that has the pattern of "Subject: Webservices restarted", you can do the following:
Select-String -Path .*.MSG -Pattern 'Subject: WebServices Restarted'
-List | select-object Filename
Also, to remove these files on the fly, you could pip into a ForEach statement with the RM command as follows:
Select-String -Path .*.MSG -Pattern 'Subject: WebServices Restarted'
-List | select-object Filename | foreach { rm $_.FileName }
I tried this myself, works 100%.
I hope this helps