I came up with this command to show all the files inside a directory with a specific size:
Get-ChildItem -path Z:\htdocs\zz -recurse | where { $_.Length -eq 2254 }
Now I would like to know HOW MANY results were returned... how do I do that?
Using measure I can count but I cant compare it with a number... for example, i would like to compare it to 3, if it is equal to 3 files I would like to do some stuff.
EDIT
I also want to delete the files. I came up with this code but it is not actually deleting the files AND it does not display at the end the amount of files deleted:
Get-ChildItem -path Z:\htdocs\zz | where { $_.Length -eq 2254 } | ?{Remove-Item $_.fullname -WhatIf}
The Measure-Object cmdlet can count objects.
$objectCount = Get-ChildItem Z:\htdocs\zz -Recurse |
Where-Object { $_.Length -eq 2254 } |
Measure-Object |
Select-Object -ExpandProperty Count
You want the Count property of the Measure-Object output object.
try this:
$(Get-ChildItem -path Z:\htdocs\zz -recurse | where { $_.Length -eq 2254 }).Count
by putting it in brackets and adding the $ you "speak" to the result object and can then use the object function Count
Related
I am trying to get file creation date into a variable in powershell, however unable to do so. The "$_.CreationTime" just prints the string literal ".CreationTime". How to get actual creation time of file?
$builds = Get-ChildItem "$path_to_directory" *.zip | Where-Object {$_.CreationTime -gt $lastBuildDeployedTimestamp}
foreach($build in $builds)
{
"$path_to_directory"
"$_.CreationTime"
}
Use "$($_.CreationTime)" .
In your particular example it should be "$($build.CreationTime)"
A one liner approach would be
Get-ChildItem $path_to_directory *.zip | Where-Object {$_.CreationTime -gt $lastBuildDeployedTimestamp} | Select-Object -Property FullName, CreationTime
However, if you'd like to keep your loop then you'll need to use $build.
$builds = Get-ChildItem $path_to_directory *.zip | Where-Object {$_.CreationTime -gt $lastBuildDeployedTimestamp}
foreach($build in $builds)
{
$path_to_directory
$build.CreationTime
}
For more info see Get-Help about_Foreach -Full
I was wondering how I can display a list of empty files in a directory
$test = gci "C:\Users\Freedom\Documents" -Recurse
$test | Where-Object {$_.PsISContainer} | Select-Object FullName | Where-Object {$_.GetFiles() -eq 0}
I Don't understand because when I do get-childitem | get-member I get a list of properties and methods I can use and in the list is getfiles() why can't I use this method why's it giving me an error message?
Method invocation failed because [System.IO.FileInfo] does not contain a method named 'GetFiles'.
I think you want this:
Get-ChildItem | Where-Object { (-not $_.PSIsContainer) -and ($_.Length -eq 0) }
If you have PowerShell 3.0 or later you can use this:
Get-ChildItem -File | Where-Object { $_.Length -eq 0 }
Of course you can add whatever other parameters for Get-ChildItem that you want (-Recurse, etc.).
Wow I had what I wanted mixed up! And I had to add the .count to the getfiles() method
$test | Where-Object {$_.PsISContainer} | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName
try this
Get-ChildItem "c:\temp" -File -Recurse | where Length -eq 0
Use Get-ChildItem and the File flag, -Recurse is needed to get every file in the folder and in the folder below. Then get all the files were Get-Content returns null.
Get-ChildItem $YourPath -Recurse -File | Where-Object {!(Get-Content $_.Fullname)}
I'm trying to run the script below in multiple paths using an array. My goal is to delete folders keeping the last 7 versions, but it is not working as expected. The action is only taking into account the first path D:\Test1.
I believe that I should add something like ($folders in $folders) after ForEach-Object but I don know how.
Any idea what I missing here?
$path = #("D:\Test1","D:\Test2","D:\Test3")
$folders = Get-ChildItem -Path $path -Recurse |
Where-Object { $_.PSIsContainer } |
Group-Object { $_.Name.Split('_')[0] } |
ForEach-Object $Folders {
$_.Group |
sort CreationTime -Descending |
Select -Skip 7 |
foreach { Remove-Item $_.FullName -Force -WhatIf }
}
This should do your job.
$path= #("D:\Test1","D:\Test2","D:\Test3")
$folders= Get-ChildItem -path $path -Recurse | Where-Object {$_.PsIsContainer} |Group-Object {$_.FullName.Split('_')[0] }
ForEach($folder in $folders)
{
$folder.Group | sort CreationTime -Descending | Select -Skip 7|% { Remove-Item $_.fullname -Force -whatIf}
}
I tested in my local and it is working fine. Although I didn't get any error in your code except few formatting issue which I have taken into variable and sorted it out cause I got tangled in too many pipeline objects.
If you are using foreach after a pipeline , that means it will take the pipeline objects one by one only. But if you are separately using it , then you have to assign each iteration into a variable.
Hope it helps you.
I got the answer from #Robert Israelsson !
" If you change your group-object to not group by name but instead fullname you will get the desired result."
From:
$folders= Get-ChildItem -path $path -Recurse | Where-Object {$_.PsIsContainer} |Group-Object {$_.Name.Split('_')[0] }
To:
$folders= Get-ChildItem -path $path -Recurse | Where-Object {$_.PsIsContainer} |Group-Object {$_.FullName.Split('_')[0] }
And this works perfectly!
My ultimate goal is to get a list of top level folders (for a given path) where a file has been modified in the last day.
There are probably a lot of ways to do this. The place where I am having a problem is getting the top level folder only.
Here is what I have so far:
Get-ChildItem -Path "c:\data\*" -recurse |
where-object {$_.lastwritetime -gt (get-date).addDays(-1)} |
where-object {-not $_.PSIsContainer} |
Foreach-Object { $_.DirectoryName} |
sort -unique
It gets all the directories though, not just the top level.
Here's how I would do it
$dirs = dir "sometoplevelpath" |?{ $_.PsIsContainer }
$oneDayAgo = (Get-Date).AddDays(-1)
$dirs |?{ dir $_ -Recurse |?{!$_.PsIsContainer -and $_.LastWriteTime -gt $oneDayAgo } | select -first 1 }
You could take the list of folders that you end up with and compare their full path without their name and see if it matches the directory that contains the folders you're interested in:
$folders | Where-Object {$_.FullName.Replace($_.Name,"") -eq $superDirectory}
Where $superdDirectory is the name of the directory that contains the "top level directories". In this case, that sounds like "C:\".
You could also investigate the PSParentPath property.
Another method would be to make a list of potential backup folders first:
$targetFolders = Get-Item -Path "C:\data*" | Where-Object {$_.PSIsContainer}
And then go through that list to see if they have any items that need backing up, taking action if they do.
$targetFolders | % {
$folderItems = Get-ChildItem $_.FullName | ? {.... use your filter here}
if (($folderItems | Measure-Object).Count -gt 0){
#Backup the folder, or add $_.FullName to the list of folders that should be backed up.
}
}
Try removing the -recurse
Get-ChildItem -Path "c:\data*" | where-object {$_.lastwritetime -gt (get-date).addDays(-1)} | where-object {-not $_.PSIsContainer} | Foreach-Object {$_.DirectoryName} | sort -unique
I also changed the $. to $_.. See if this works. I got it to give me only the top level directory names, but I don't have anything I can run as a pattern like "c\data*"
I'm having trouble getting the following PowerShell statement to work. The objective is to get a list of folders which are in the ..\archive folder sorted by oldest to youngest.
I would like to copy the number of folders which amount to or less than $ClosedJobssize from the ..\Archive to the ..\movetotape folder. This is so the size of the ..\Archive folder never changes on the hard drive.
get-childitem -path "\\srv02\d$\Prepress\Archive" | sort-object -property
#{Expression={$_.CreationTime};Ascending=$false} | % { if (((get-childitem -path
"\\srv02\d$\prepress\archive" -recurse -force | measure-object -Property Length -Sum).Sum + $_.Length)
-lt $closedjobssize ) { move-item -destination "\\srv02\d$\prepress\archive\MoveToTape\" }}
What might I be doing wrong? I don't get any errors. It just sits and hangs when I execute it.
Try this. It's a long one-liner (remove -whatIf to perform the move):
dir "\\srv02\d$\Prepress\Archive" | sort CreationTime -desc | where { $_.psiscontainer -AND (dir $_.fullname -recurse -force | measure-object -Property Length -Sum).Sum -lt $closedjobssize} | Move-Item -dest "\\srv02\d$\prepress\archive\MoveToTape\" -whatIf
I'm not quite sure I understand. But I think you want to move folders in \archive to \archive\movetotape to fill up \movetotape until it is $ClosedJobsSize or less in size. Right?
A couple of things: You are adding up the size of everything in \archive, so the result of your comparison will never change. Second, one of the folders checked is MoveToTape itself, which could cause you to move it into itself (this should give an exception).
Given that, I think this code will work, but I haven't tested it.
## Get all the directories in \arcive that need to be moved
$Directories = Get-ChildItem "\\srv02\d$\Prepress\Archive" |
Where-Object {$_.PSIsContainer -and ($_.Name -ne "MoveToTape")} | Sort-Object CreationTime -Descending
foreach ($Directory in $Directories)
{
$SumOfMoveToTape = (Get-ChildItem "\\srv02\d$\prepress\archive\MoveToTape\" -Recurse | Measure-Object -Property Length -Sum).Sum
$SumOfItem = (Get-ChildItem $_.FullName -Recurse | Measure-Object -Property Length -Sum).Sum
if(($SumOfMoveToTape + $SumOfItem) -lt $ClosedJobsSize)
{
## If we can fit on MoveToTape, then move this directory
Move-Item -Destination "\\srv02\d$\prepress\archive\MoveToTape\"
}
## If you want to keep folders in order (and not try to squeze whatever onto the tape
## then put an 'else {break}' here
}