I created a script that allows me to search for and ignore directories from a Remove-Item statement, and the script works, but not necessarily to the extent I need it to.
Get-ChildItem -Path $Path |
Where-Object {
($_.LastAccessTime -lt $Limit) -and
-not ($_.PSIsContainer -eq $True -and $_.Name -contains ("2013","2014","2015"))
} | Remove-Item -Force -Recurse -WhatIf
This script is currently finding and deleting all objects that
Have not been accessed in the given time period
But what I need this script to do is find and delete all objects that
Have not been accessed in the given time period AND
Exclude directories that contain the name of "2013", "2014", or "2015".
I'm not arguing that the script "isn't working properly", but the thesis of my question is this:
How do I program this script to look at the directory name first, and then the last access date? I don't know where and how to tell this script that the $_.Name needs to take precedence over the $_.LastAccessTime -lt $Limit.
Currently the logic of your condition is this:
Delete objects that were last accessed before $Limit and are not folders whose name contains the array ["2013","2014","2015"].
The second condition is never true, because a string can never contain an array of strings.
Also, the last modification time is stored in the LastWriteTime property.
What you actually want is something like this:
Where-Object {
$_.LastWriteTime -lt $Limit -and
-not ($_.PSIsContainer -and $_.Name -match '2013|2014|2015')
}
If the directory names consist only of the year and nothing else you could also use this:
Where-Object {
$_.LastWriteTime -lt $Limit -and
-not ($_.PSIsContainer -and '2013','2014','2015' -contains $_.Name)
}
Note the reversed order of the last clause (array -contains value).
Related
I am writing a PowerShell script to sort the directory and return folders with the names that start with the number sequence that is greater than specified sequence, but -gt operator acts as a -ge operator.
Here is the code I'm running:
Get-ChildItem C:\Users\USER\Testing -recurse |
Where-Object { $_.PSIsContainer -ge $true -and $_.Name -gt "003" -and $_.Name -match '^\d+.*$' } |
Select-Object Name
The response I get is:
005-folder
003-folder
004-folder
There seems to be the similar but opposite pattern for -le and -lt operators. Both of them do NOT include the equal item. So when I run
Get-ChildItem C:\Users\USER\Testing -recurse |
Where-Object {$_.PSIsContainer -ge $true -and $_.Name -le "003" -and $_.Name -match '^\d+.*$' } |
Select-Object Name
The response I get is:
001-folder
002-folder
I can't seem to find anything on the internet that solves the issue I am having, so I assume something in my scripts breaks the -gt and -le operators?
I think I figured out the issue few minutes after I posted it. '003-folder' will be greater than '003' cause I'm comparing strings. Need to truncate first.
Get-ChildItem C:\Users\USER\Testing -recurse -Directory |
Where-Object {$_.Name.subString(0, 3) -gt '003' -and $_.Name -match '^\d+.*$' } |
Select-Object Name
The below function flattens the directory structure and copies files based on the last write date chosen.
function mega-copy($srcdir,$destdir,$startdate,$enddate)
{
$files = Get-ChildItem $SrcDir -recurse | Where-Object { $_.LastWriteTime -ge "$startdate" -and $_.LastWriteTime -le "$enddate" -and $_.PSIsContainer -eq $false };
$files|foreach($_)
{
cp $_.Fullname ($destdir+$_.name) -Verbose
}
}
This has been very successful on smaller directories, but when attempting to use it for directories with multiple sub-directories and file counts ranging from the hundreds of thousands to the tens of millions, it simply stalls. I ran this and allowed it to sit for 24 hours, and not a single file was copied, nor did anything show up in the PowerShell console window. In this particular instance, there were roughly 27 million files.
However a simplistic batch file did the job with no issue whatsoever, though it was very slow.
Simple answer is this: using the intermediate variable caused a huge delay in the initiation of the file move. Couple that with using
-and $_.PSIsContainer -eq $false
as opposed to simply using the -file switch, and the answer was a few simple modifications to my script resulting in this:
function mega-copy($srcdir,$destdir,$startdate,$enddate)
{
Get-ChildItem $SrcDir -recurse -File | Where-Object { $_.LastWriteTime -ge "$startdate" -and $_.LastWriteTime -le "$enddate" } | foreach($_) {
cp $_.Fullname ($destdir+$_.name) -Verbose
}
}
I am currently working on a script that will count all of the directories (within a specified path, \\servername\logs\failures) which have a naming convention of "P0*" or "MININT*" - but the folders named as "MININT*" also must have a subfolder that contains a specified log file. Also, it should only be counting folders created in the last 24 hours.
Here is my current code, it keeps returning a zero value and I am not sure why. I have been searching for hours and tried different methods using recurse, Test-Path, etc. to no avail.
$imagefailures = Get-ChildItem '\\servername\logs\failures' -Directory |
Where-Object {
($_.Name -like "P0*") -or
(($_.Name -like "MININT*") -and (Test-Path "\WinPE_TS_X_Win\SMSTSLog\Get-Name.log")) -and
($_.LastWriteTime -gt (Get-Date).AddHours(-24))
} | Measure-Object | select -ExpandProperty Count
Try this:
$imagefailures = Get-ChildItem '\\servername\logs\failures' -Directory |
Where-Object {
($_.Name -like "P0*") -or
(($_.Name -like "MININT*") -and (Test-Path "$($_.FullName)\WinPE_TS_X_Win\SMSTSLog\Get-Name.log")) -and
($_.LastWriteTime -gt (Get-Date).AddHours(-24))`
} | Measure-Object | select -ExpandProperty Count
The path you are testing will always just be "\WinPE_TS_X_Win\SMSTSLog\Get-Name.log" if you do not append it to the folder path you are iterating on.
I am writing a script that checks, recursively, all folders and file names in a directory, and then returns the names and last write times to a text file. I only want the names of files and folders that have been added within the past twenty four hours.
$date = Get-Date
Get-ChildItem 'R:\Destination\Path' -recurse |
Where-Object { $_.LastWriteTime -lt $date -gt $date.AddDays(-1) } |
Select LastWriteTime, Name > 'C:\Destination\Path\LastWriteTime.txt' |
Clear-Host
Invoke-Item 'C:\Destination\Path\LastWriteTime.txt'
The .txt file that is invoked is blank, which, based on the test conditions I have set up should not be the case. What am I doing wrong?
You are missing a logical and. Change:
Where-Object { $_.LastWriteTime -lt $date -gt $date.AddDays(-1) }
to
Where-Object { $_.LastWriteTime -lt $date -and $_.LastWriteTime -gt $date.AddDays(-1) }
Even better to use parenthesis, if you would have used them then the syntax would not have been parsed with the missing AND:
Where-Object { ($_.LastWriteTime -lt $date) -and ($_.LastWriteTime -gt $date.AddDays(-1)) }
I'm looking into building a script that will get me both a date and parent directory of files created during a certain period.
So far this is what I've come up with:
get-childitem –recurse | where-object {($_.lastwritetime -gt “7/1/2013”) -and ($_.lastwritetime -le “7/22/2013”) }
I'm a bit clueless as to how to separate "Directory" and "LastWriteTime" (minus the time) into variables.
Would appreciate the help.
Thanks!
I wouldn't put them into separate variables. I'd just select the 2 properties:
$files = Get-ChildItem –Recurse | ? {
-not $_.PSIsContainer -and
$_.LastWriteTime -gt "7/1/2013" -and
$_.LastWriteTime -le "7/22/2013"
} | select Directory, #{n='LastWriteDate';e={Get-Date -uformat "%m\/%d\/%Y"}}
Then you can access those values like this:
$files[0].Directory.FullName
$files[0].LastWriteDate