Removing Files From a Path Older Than 60 Days Old Fails - powershell

I have a powershell script that removes log files older than 60 days. It gets to a particular file and fails saying the file doesn't exist. The funny thing is the code is not pointing to a particular file but the folder. I changed the path to not reveal anything about my environment. Sample below. Any ideas?
clear-Host
$limit = (Get-Date).AddDays(-60)
$Path = 'C:\Windows\Temp'
Get-ChildItem $Path | Where-Object { -not $_.PSIsContainer -and $_.CreationTime -lt $limit -and $_.LastWriteTime -lt $limit } | Remove-Item

Some things to look at:
Is it safe to just nuke the %tempdir%?
Nowadays most apps will write to files in %localAppdata%\Temp which is in the user profile, so it's mostly Windows OS services using \Temp, which makes the C:\Windows\Temp path sort of a special directory. Sometimes processes might be running that have a lock on a file in that directory, and if you delete them, things can go poorly for the process. Those errors tend to look like this:
Remove-Item : Cannot remove item C:\temp\stack\2.txt:
The process cannot access the file 'C:\temp\stack\2.txt' because
it is being used by another process.
However, these are not terminating errors, which means the rest of the directory will get cleaned out. So if you don't care about the error, you could just append -ErrorAction SilentlyContinue to your Remove-Item cmdlet and consider the ticket done.
Your code isn't just removing log files though.
You mentioned that you want to delete only log files. In that case, you might want to append a file filter to only remove logs because today your code is going to nuke the whole directory. Adding a filter is really easy, it would look like this:
Get-ChildItem -Filter *.log | Where {#....

Related

Could you help me with a script (made on Powershell) to delete files (eventualy subfolders) of a specific folder that are older than 5 days?

As I said in the question, I have tried to create a script that would delete files and subfolders of a folder that are older than 5 days.
I am new to Powershell, I have already seen some tutorials and read about the syntax of it, but that has not helped me much, so I just found a code that is alike the one I need and I have tried to adapt it to my needs. I will paste it here:
$limit = (Get-Date).AddDays(-5)
$path = "C:\Users\Me\Desktop\example"
Get-ChildItem -Path $path -Recurse | Where-Object {$_.PSIsContainer -and
$_.CreationTime -lt $limit} | Remove-Item
The script has runned, without any error message, but the files have not been deleted. I would like to know what may be the problem. By the way, would this script delete subfolders as well? Other thing, how do I do to schedule this script?
Note: As I said, I am a beginner, so if someone could clarify these objects for me, I would be very glad: "PSIsContainer", "CreationTime", "|". I have already search what this "$_." means, but I have not understood it well yet, so if someone could tell me it directly, I would be very thankful as well. Thank you in advance.
I have tried a different code structure, but that basically does the same thing, and it has worked:
$Now=Get-Date
Get-Childitem C:\Users\Me\Downloads | Where-Object { $_.LastWriteTime –lt
$Now.AddDays(-5) } | Remove-Item
Now I am just not sure if it will delete subfolders as well, and I still need to schedule it, but I will keep on trying it and if I get it, I will bring some update about it here.

How do I prevent Get-ChildItem from traversing a particular directory?

Let me start by saying that I've looked at Unable to exclude directory using Get-ChildItem -Exclude parameter in Powershell and How can I exclude multiple folders using Get-ChildItem -exclude?. Neither of these has an answer that solves my problem.
I need to search a directory recursively for files with a certain extension. For simplicity, let's just say I need to find *.txt. Normally, this command would suffice:
Get-ChildItem -Path 'C:\mysearchdir\' -Filter '*.txt' -Recurse
But I have a major problem. There's a node_modules directory buried somewhere inside C:\mysearchdir\, and NPM creates extremely deep nested directories. (The detail of it being an NPM managed directory is only important because this means the depth is beyond my control.) This results in the following error:
Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
I believe this error bubbles up from the limitations in the .NET IO libraries.
I can't search in the other directories around it very easily. It's not at the top of the directory; it's deeper in, say at C:\mysearchdir\dir1\dir2\dir3\node_modules, and there are directories I need to search at all those levels. So just searching the other directories around it is going to be cumbersome and not very maintainable as more files and directories are added.
I've tried to -Exclude parameter without any success. That isn't surprising since I just read that -Exclude is only applied after the results are fetched. I can't find any real info on using -Filter (as is noted in this answer).
Is there any way I can get Get-ChildItem to work, or am I stuck writing my own recursive traversal?
Oh, man, I feel dumb. I was facing the same problem as you. I was working with #DarkLite1's answer, trying to parse it, when I got to the "-EA SilentlyContinue" part.
FACEPALM!
That's all you need!
This worked for me, try it out:
Get-ChildItem -Path 'C:\mysearchdir\' -Filter '*.txt' -Recurse -ErrorAction SilentlyContinue
Note: This will not exclude node_modules from a search, just hide any errors generated by traversing the long paths. If you need to exclude it entirely, you're going to need a more complicated solution.
Maybe you could try something like this:
$Source = 'S:\Prod'
$Exclude = #('S:\Prod\Dir 1', 'S:\Prod\Dir 2')
Get-ChildItem -LiteralPath $Source -Directory -Recurse -PipelineVariable Dir -EV e -EA SilentlyContinue |
Where {($Exclude | Where {($Dir.FullName -eq "$_") -or ($Dir.FullName -like "$_\*")}).count -eq 0}

How to limiting files searched by Get-ChildItem (or limiting depth of recursion)?

Background
There is a directory that is automatically populated with MSI files throughout the day. I plan on leveraging Task Scheduler to run the script shown below every 15 minutes. The script will search the directory and copy any new MSIs that have been created in the last 15 minutes to a network share.
Within this folder C:\ProgramData\flx\Output\<APP-NAME>\_<TIME_STAMP>\<APP-NAME>\ there are two other folders: Repackaged and MSI Package. The Repackaged folder does not need to be searched as it does not contain any MSIs. Also I have found that it needs to be excluded in some way to prevent this error:
Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:14 char:32
+$listofFiles=(Get-ChildItem <<<< -Recurse -Path $outputPath -Include "*.msi" -Exclude "*.Context.msi" | where {$_.LastAccessTime -gt $time.AddMinutes($minutes)})
+ CategoryInfo : ReadError: C:\ProgramData\...xcellence\Leg 1:String) [Get-ChildItem], PathTooLongException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
Limitations
I am stuck using Powershell v1.0
I have no control over the directory structure of the source location
Updated:
I don't know the app name or the what the time stamp will be. That is something else that is out of my control.
Current plans
I have read about using -Filter and I am aware of filters that are similar to functions but I wasn't able to come up with any ideas of how to use them. My only thought at the moment would be to do something like:
$searchList=Get-ChildItem "all instances of the MSI Package folder"
foreach($folder in $searchList){
$listofFiles=Get-ChildItem "search for *.msi"
foreach($file in $listofFiles){"Logic to copy MSI from source to destination"}
}
However...I thought that there might be a more efficient way of doing this.
Questions
How can I limit depth that Get-ChildItem searches?
How can I limit the Get-ChildItem search to C:\ProgramData\flx\Output\<APP-NAME>_<TIME_STAMP>\<APP-NAME>\MSI Package
How can I only search folders that have been accessed in the last 15 minutes? I don't want to waste time drilling down into folders when I know MSI has already been copied.
Any additional advice on how to make this script more efficient overall would also be greatly appreciated.
Script
My current script can be found here. I kept getting: "Your post appears to contain code that is not properly formatted as code" and gave up after the fourth time trying to reformat it.
You can try this
dir C:\ProgramData\flx\Output\*\*\*\*\* -filter *.msi
this search all .msi files at this level
C:\ProgramData\flx\Output\<APP-NAME>\_<TIME_STAMP>\<APP-NAME>\Repackaged or 'MSI Package' or whatever else present folder
without recursion, this avoid too deep folder that give you error.
Pipe the result to:
Where {$_.LastAccessTime -gt (Get-Date).AddMinutes(-15)} #be sure no action on file is taken before the dir command
or
Where {$_.LastWriteTime -gt (Get-Date).AddMinutes(-15)} #some file can be re-copied maybe
With help from C.B. this is my new search which eliminates the issues I was having.
Changed -Path to C:\ProgramData\flx\Output\*\*\*\* to help limit the depth that was searched.
Used -Filter instead of -Include and put the -Exclude logic into the where clause.
Get-ChildItem -Path C:\ProgramData\flx\Output\*\*\*\* -Filter "*.msi" | where {$_.Name -notlike "*.Context.msi" -and $_.LastAccessTime -gt (Get-Date).AddMinutes(-15)}
You can't limit the recursion depth of Get-ChildItem except to not use -Recurse i.e. Get-ChildItem is either depth = 0 or N.
Set up variables for app name and timestamp e.g.:
$appName = "foo"
$timestamp = Get-date -Format HHmmss
Get-ChildItem "C:\ProgramData\flx\Output\${appName}_$timestamp\$appName\MSI Package" -force -r
You can filter the results like so:
Get-ChildItem <path> -R | Where {$_.LastWriteTime -gt (Get-Date).AddMinutes(-15)}

Trying to move files with specific file names from root directory to a subfolder

Hi I'm still pretty new to powershell so I apologize if I ask something that extremely basic. I have a root directory on a tftp server that pulls down config files from routers and other equipment every night. The files are like this IPaddress_YYYYMMDD_TA5000. There is a limitation in the equipment where the files can't be set to move into the root directory on their own.
What I want to do is make a powershell script that will only move the files with the TA5000 part in the filename to the sub directory and only keep the 5 most recent files.
I looked but I couldn't seem to find what I would need to do to parse the file for that specific string. I already have the portion of the script to delete the files based on age that was simple.
Any help on getting started would be appreciated.
Edit: I forgot to post the code I was trying.
Move-Item c:\tftptransferfiles c:\tftptransferfiles\sca | Where-Object {_.name -like "*TA5000*"}
I keep getting a error saying that the item at C:\tftptransferfiles is in use.
Get-ChildItem $path -filter "*TA5000"
or maybe:
Get-ChildItem $path | Where-Object {$_.name -like "*TA5000*"}

Get powershell to display all paths where a certain file can be found on a drive

I'm trying to build a function that will show me all path's where a certain filename is located. The function would take one parameter, that being the file name.
The result would be either a list of all paths, or a message saying there's no such file on the system.
I'm new to Powershell, and I'm not getting the syntax just yet.
I've tried this:
Get-ChildItem -Path -Include notepad.exe
But that threw an error message. I'm currently trying:
$i="notepad.exe"
Foreach ($i in Get-ChildItem c:\ -Recurse){echo -Path}
Started that now, it's still running, don't know what'll happen, really.
EDIT: echo'd an enormous amount of lines that just say "-Path"...
Can anybody help with this problem? I'm running Powershell 1.0 by the way.
So, to explain what I wish to see when executing this command, here is an example of what I expect after looking for *.txt:
C:/foo.txt
C:/A/foobar.txt
C:/A1/foo.txt
And so on, listing the path to all .txt files on my harddrive. Only the paths, one per line, no extra info needed.
EDIT2:
I've done it. I'm gonna leave this question up for those who make look for this in the future.
The function I used was this(this specific example will hand you a list of all .zip files on your harddrive, edit where needed):
Get-ChildItem -Path c:\ -Include "*.zip" -Recurse -Force -Name > c:\listOfPaths.txt
This created a file called listOfPaths.txt on my C:\ folder and this contained a list of all occurences of any file ending with .zip in all subfolders of my harddrive.
The "c:\" bit isn't mentioned, but I don't mind.
EDIT3:
thanks capar for a more complete version.
Here is capar's code(or how I got it to work, since Get-Children doesn't work in 1.0)
Get-ChildItem -Path c:\ -Recurse *.txt | Select-Object -Property FullName
Since it's Friday night, I decided to play with Power Shell to see if I can help :)
This comes pretty close to what you are asking for I think:
Get-ChildItem -Path c:\ -Recurse *.txt | Select-Object -Property FullName
If it helps, this command will list the properties of any object that will be returned by Get-ChildItem:
Get-ChildItem | Get-Member
ls c:\ -r | ? {$_.name -eq "notepad.exe"}
Get-Children is not recognized in Powershell V3 either. It would be great if someone removed that bad example.
As a warning to anyone searching for files: C:\ on today's hard drives will take a long time to run. You are well advised to narrow your search as much as you can. Since your folder structure might include spaces or special characters, use the typewriter quote (") or apostrophe (') delimeters.
$mylistoffiles = Get-ChildItem -Path 'C:\Windows\Setup\Scripts' -Recurse *.cmd | Select-Object -Property FullName
$mylistoffiles