So I've started working on a problem where I need to know how many files are in a subfolder of a certain name, that is repeated multiple times in throughout the directory. All folders I want to count have the same name. For example:
Main Folder
Subfolder
Folder I want to count
Folder A
Folder B
Subfolder
Folder I want to count
Folder C
Folder D
I'm able to count the number of files in all subfolders recursively, but I don't know how to only look at folders named " Folder I want to count ".
This is where I've gotten so far to count everything. What do I need to add/modify to only look at and count in the area I want. I'm not familiar with supershell, and have been working to make sense of various questions and cobble this together.
Get-ChildItem -recurse | Where {!$_.PSIsContainer} | Group Directory | Format-Table Name, Count -autosize
I would probably do something like this.
First get all the folders, then run through them. And if the folder is the "folder_I_want", get the count.
$folders = Get-ChildItem C:\Users\David\Documents\SAPIEN\test -Recurse | ?{ $_.PSIsContainer } | select name, fullname
foreach ($folder in $folders)
{
#Write-Host "$folder"
if ($folder.name -eq "folder_I_want")
{
$fullname = $folder.fullname
#Gets the count of the files in "Folder I want". It will filter out folders.
$count = (Get-ChildItem $fullname | where { $_.PSIsContainer -EQ $false }).count
Write-Host "The amount of files in the folder I want: $count"
}
}
somthing like this?
(gci -Path c:\temp\ -Recurse -File | where fullname -like "*\yourname\*").Count
Related
I'd like to get an overview of the latest accessed file per profile directory out of a list of profile directories and then write the result in a file.
Given:
A folder with a ton of profile directories in it. In every profile directory, there are more folders and files.
Wanted:
I need the date with the name of the profile directory of the latest accessed file of each profile directory within the parent folder.
What I already have:
With the following commands, the output file lists the last accessed file out of all files in the whole directory times the count of profile directories in the folder:
cd \\Servername\Patch\Profiles
$folder = Get-ChildItem -Directory
$folder | ForEach-Object {
Get-ChildItem -Recurse |
Sort-Object -Property LastAccessTime -Descending |
Select-Object -First 1
} | Out-File "C:\Users\User-abc\Desktop\Log.txt"
So I tried to add the specific path for each profile folder within the parent folder to the Get-ChildItem command like this:
... ForEach-Object {
Get-ChildItem -Path ".\$folder" -Recurse |
Sort-Object ...
I also tried to add a .Name to the $folder variable and to remove the " or put ' instead of ", but nothing helped. I always get the response that there is no parameter found for the parameter -Path.
I also tried to remove the -Path parameter but let the .\$folder or even add a [0] or [1] to the $folder variable, but that also doesn't help.
Call Get-ChildItem on the full path of the current object in the pipeline:
Get-ChildItem \\Servername\Patch\Profiles -Directory | ForEach-Object {
Get-ChildItem $_.FullName -Recurse |
Sort-Object -Property LastAccessTime -Descending |
Select-Object -First 1
}
I have the directory E:\NugetRoot\NugetServer where I need to cycle through the subdirectories on this path and within the packages folder within that subdirectory I need to count the files ending in .nupkg and output them to a cvs file named d:\monitoring\NugetStatistics and each time the script is run, it should append to the file.
Count the files ending in .nupkg in "C:\NugetRoot\NugetServer\\**\Packages" for each folder. (I need to Loop through the ** folders and count each file ending on .nupkg)
Output in cvs file with two columns: one showing the "**" folder name & the other showing the file count.
First find all the *.nupkg files using Get-Childitem with the recurse flag to get all files in sub folders, then filter the results using a regex to exclude any where the final folder is not called Package. Then use another regex to extract the previous folder name, feed that in to a Group-Object to get the count and then into a Export-Csv which includes the append flag.
cd E:\NugetRoot\NugetServer
Get-ChildItem -Filter *.nupkg -Recurse | ? {
$_.DirectoryName -match '\\Packages$'
} | % {
$_.DirectoryName -Replace '^.*\\([^\\]+)\\Packages$', '$1'
} | Group-Object | Select Name, Count | Export-Csv outfile.csv -Append -NoTypeInformation
cd "C:\NugetRoot\NugetServer\\**\Packages"
$a = Get-ChildItem -Name
foreach ($i in $a) {
$b = (Get-ChildItem -Recurse -Force -Include .nupkg -Path $i | Select-Object -ExpandProperty Name).Count
$i + "`t" + $b
}
Here's what I have so far. It displays the server name, ProjectgroupID(or folder name), but get error for package count. Also, I am having trouble getting the average file size as well, I commented those out:
$folders = gci C:\NuGetRoot\NugetServer -Directory
foreach($folder in $folders){
#{ServerName=$env:COMPUTERNAME;
ProjectGroupID = $folder.Name;
NuGetPackageCount = (gci $folder.FullName\packages -Include '*.nupkg') | %{$_.Size}.Count;
#AverageSize= Measure-Object (listof sizes) -Average
} #| Export-Csv -Path c:\temp -NoTypeInformation -Append
}
Measure-Object -Average
Using powershell I would like to search through an array of sub-folders in multiple directories containing 1 folder called incoming and move the files from incoming to a staging area using the same folder name as its source.
IE: Files arrive in folders like this:
z:\folder1\incoming\file.*, z:\folder2\incoming\file.*, z:\folder3\sub1\incoming\file.*, z:\folder3\sub2\incoming\file.* etc.
Then would need to be moved to a staging area using the same folder structure:
\nas\staging\folder1\incoming\file.*, \nas\staging\folder2\incoming\file.*, \nas\staging\folder3\sub1\incoming\file.*, \nas\staging\folder3\sub2\incoming\file.* etc.
Basically the only sub-folders i want to extract from are the ones containing the "Incoming" folder with files. Since there is no predefined folder names other than the sub-folder "Incoming" i would need to loop through every folder within Z:.
Any help or advice would be greatly appreciated.
I was able to come up with this which affectively moves the folder structure excluding "outgoing" to the staging directory which is great but in my environment there would be to many exclusions to check for this way. Also is there a chance i can move the files to specific folders from maybe a list if needed?
$from = 'C:\ftp'
$to = 'C:\staging'
$excludeMatch = #("Outgoing")
Get-ChildItem -Path $from -Recurse -Exclude $exclude |
where { $excludeMatch -eq $null -or $_.FullName.Replace($from, "") -notmatch $excludeMatch } |
Copy-Item -Destination {
if ($_.PSIsContainer) {
Join-Path $to $_.Parent.FullName.Substring($from.length)
} else {
Join-Path $to $_.FullName.Substring($from.length)
}
} -Force -Exclude $exclude
Sooooo, what we need is, to identify any file whos parent directory is called 'incoming'? There are at least two ways of solving this I can think of, but there may be a neater, more idiomatic solution that eludes me.
Method 1 - Identify 'incoming' folders then copy contents
get-childitem -Path $from -recurse -Filter "incoming" |
where-object { $_.PSIsContainer }
If you are using PowerShell 3, I believe (read 'untested') this could be shortened to
get-childitem -Path $from -recurse -Filter "incoming" -Directory
Either of the above should result in a stream of 'directory' objects, all of which are 'incoming' folders. For each one, copy the files to appropriate destination.
Method 2 - Identify all files then process those whos folder is 'incoming'
get-childitem -path $from -recurse |
where-object { -not $_.PSIsContainer } |
where-object { (Split-Path $_.Directory -Leaf) -eq "incoming" }
This results in a stream of 'file' objects, all of which are in a folder called 'incoming'. For each one, copy to appropriate destination.
I am trying to use a do while loop to remove old files in multiple directories (starting from the oldest) until there is one left, at which point the program should end. The program should also only run if there is more than one file in the directory at runtime.
Here is my environment:
Top Folder
Folder 1
Folder 2
etc
In Folder 1, Folder 2, etc there should only be one file. The script should delete everything but the latest and nothing at all if there is only one file in there to begin with.
I have semi-accomplished this using the following code:
$basedir = "C:\Test"
Set-Location -Path C:\Test
$a = Get-ChildItem -recurse $basedir
if ($a.Count -gt 1) {
do
{
$a | Sort-Object LastWriteTime -Descending | Select-Object -Last 1 | remove-item
}
while
(
$a.Count -gt 1
)
}
It will only run when there is more than one file present, which is correct.
It correctly deletes the oldest file, but then it keeps on trying to delete the same file rather than rechecking the directory.
All I need help with at this point is getting it to re-run the loop once it has deleted a file, rather than trying to delete the same file over and over.
Thank you, sincerely, for any help and I apologise if this has been answered before. I did a lot of searching but couldn't find something with my situation.
Brad
To fix yours, you should re-define $a every time you pass through the loop, or just avoid using $a altogether. $a doesn't change just because the child items that were there when you created the object have.
Another way to do it would be to just select the last n-1 items in the folder.
#Get Items that aren't folders
$items = Get-ChildItems "c:\test" | ? {!($_.PSIsContainer)}
#Get a count - this is easier in PoSh 3
$itemCount = ($items | Measure-Object).Count
if ($itemCount -gt 1){
$items | Sort-Object LastWriteTime -Descending | Select-Object -Last ($itemCount - 1) | Remove-Item
}
To do this recursively is also fairly easy. First we get all of the folders we'll need to do the work in, then we'll move the code above into a foreach loop:
$folders = Get-ChildItems "C:\test" -recurse | ? {$_.PSIsContainer}
foreach ($folder in $folders) {
#Get Items that aren't folders
$items = Get-ChildItems $folder.FullName | ? {!($_.PSIsContainer)}
#Get a count - this is easier in PoSh 3
$itemCount = ($items | Measure-Object).Count
if ($itemCount -gt 1){
$items | Sort-Object LastWriteTime -Descending | Select-Object -Last ($itemCount - 1) | Remove-Item
}
}
You might need to run both scripts to prune the root as well, or add something like $folders += Get-Item "C:\test" before the foreach loop
I have a folder c:\graphics (root) and a program that creates subfolders e.g. aa, bm, czx, mjpq, zz (I have many subfolders, the length is variable).
In each subfolder, I have 26 files and one folder. For example, aa folder has: aa_000.jpg, aa_001.jpg, ..., aa_023.jpg; other two files aa_360.jpg, aa.html and a folder. The complete path is C:\graphics\aa\aa_360.
I need to move 24 files (aa_000.jpg, aa_001.jpg, ..., aa_023.jpg) in subfolder c:\graphics\aa\aa_360 and also equal to each subfolder.
Another example is c:\graphics\mjpq\mjpq_360, should have mjpq_000.jpg, ..., mjpq_023.jpg.
I started the script, thinking move all .jpg (25 files) in the subfolder (later, I had to think like extract the xxx_360.jpg) but it doesn't work:
Get-ChildItem c:\graphics -rec | where-object {$_.extension -match "jpg"} | ForEach-object {$newPath =(Get-Location).toString()+(Get-Location).ToString().SubString(10)+"_360"); Move-Item $_.FullName $newPath}
but Get-Location doesn't find the file path.
NOTE: I found a solution that is working, but it throw some errors in the console:
Get-ChildItem c:\graphics -rec | where-object {$_.extension -match "jpg" -and (!($_.name -like "*360*"))} | ForEach-Object {$newPath =($_.DirectoryName).toString()+($_.DirectoryName).ToString().SubString(10)+"_360"; Move-Item $_.FullName $newPath}
I think you can simplify this to:
Get-ChildItem c:\graphics -rec *.jpg | Move-Item -Dest {$_.Directory.FullName + "\" +
$_.Directory.Name + "_360\" } -WhatIf
Remove the -whatif if the suggested move operations look correct.