Loop/Cycle through Subdirectories and determine file count in each - loops

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

Related

How to remove duplicate files from an arraylist

A bit different from the others. I'm retrieving an arraylist of files for processing (basically handling DLL registration on a local machine), and I need my script to properly handle multiple DLLs with the same name. The select -Unique doesn't work, since technically the files aren't duplicates - each has its own unique full path.
I need this script to retrieve all DLLs in a folder (as well as sub-folders), but only return the last instance of each named file. For example if I have files:
C:\Path\Update1\GRM.DLL
C:\Path\Update1\HTCP.DLL
C:\Path\Update2\GRM.DLL
C:\Path\Update3\GRM.DLL
The script should return the objects for Update3\GRM.DLL and Update1\HTCP.DLL.
[System.Collections.ArrayList]$dlls = #(Get-ChildItem -Path $PSScriptRoot -Recurse | Where-Object
{$_.Extension -eq ".dll" -and $_.FullName -notmatch 'dll_Old'})
Edit: Got it going with this, but it's selecting the first instance that shows up, and I need the last. In this example, that means it's snagging Update1/GRM.DLL instead of Update3/GRM.DLL
$dlls = #(Get-ChildItem -Path $PSScriptRoot -Recurse | Where-Object {$_.Extension -eq ".dll" -and $_.FullName -notmatch 'dll_Old'}) | Select-Object -Unique
Use a hashtable to keep track of the last file seen for a specific file name:
$files = #{}
Get-ChildItem -Path $PSScriptRoot -File -Recurse -Filter *.dll |Where-Object FullName -notmatch 'dll_Old' |ForEach-Object {
$files[$_.Name] = $_
}
$uniqueFiles = $files.Values
Mathias R. Jessen's helpful answer is probably the best (fastest) solution in this case, but here's an alternative based on the Group-Object cmdlet:
Get-ChildItem -LiteralPath $PSScriptRoot -Recurse -Filter *.dll |
Where-Object FullName -notmatch dll_Old |
Group-Object Name |
ForEach-Object { $_.Group[-1] }
Group-Object Name groups all matching files by their .Name property.
ForEach-Object { $_.Group[-1] } then extracts the last (-1) member from each resulting group.
Note that Group-Object will implicitly sort the groups by the grouping property, so the resulting list of file-info objects (System.IO.FileInfo, as output by Get-ChildItem) will be sorted by file name.

LastAccessTime of the very last accessed File of an array of Folder

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
}

How to search Powershell array for specific strings and use this result in a copy-item -include script

I'm trying to create a synchronization script in Powershell so that my applications in MDT are being copied on a regular basis to our main file server, based on the folder name (in MDT, applications are in one folder, where our main server has applications split depending on the department who uses them).
From what I read on the web, the best way would be to populate an array with "Get-ChildItem", which I kinda figured how to do (see code below).
After the array is populated though, I don't know how to search that array for specific results, nor do I know how to use those results with copy-item.
In a nutshell, here's what I need to do: Build an array using "Get-ChildItem", query the resulting array for specific folders, and have those folders be copied to specific destinations.
Here's the code I have so far:
$arr = Get-ChildItem \\slmtl-wds02.domain.inc\deploymentshare$\applications |
Where-Object {$_.PSIsContainer} |
Foreach-Object {$_.Name}
$sourcepath = \\slmtl-wds02.domain.inc\deploymentshare$\applications
$destSLARC = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLARCMTL
$destSLMTL = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLMTL
$destSLGLB = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLGLB
$destSLTECH = \\slmtl-fs01.domain.inc\folder\it_services\private\software\service_desk\pc\SLTECH
Thanks in advance for your help :)
$sourceLocation = "c:\analysis\"
$targetLocation = "c:\analysisCopy\"
$included = #("folder1", "folder2")
$result = #()
foreach ($i in $included){
$result += get-ChildItem $sourceLocation -filter $i | Where-Object {$_.PSIsContainer}
}
$result | foreach-Object { copy-item $_.FullName -Destination $targetLocation -Recurse}
Hope this works change the path D:\ to your desired path enter the name of folder you looking for
$Keyword=[Microsoft.VisualBasic.Interaction]::InputBox("Enter your Query")
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
Get-ChildItem D:\ -recurse | Where-Object {$_.PSIsContainer -eq $fasle -and $_.Name -match "$keyword"} | Copy-Item -Destination d:\test

Comparing filenames in an array to files in a file structure

$folder = filestructure
# Get a recursive list of all folders beneath the folder supplied by the operator
$AllFolders = Get-ChildItem -Recurse -Path $Folder |? {$_.psIsContainer -eq $True}
# Get a list of all files that exist directly at the root of the folder
# supplied by the operator
$FilesInRoot = Get-ChildItem -Path $Folder | ? {$_.psIsContainer -eq $False}
Foreach ($File in ($FilesInRoot))
{
#Notify the operator that the file is being uploaded to a specific location
if($Global:successfullymigrated -contains $File){
Write-Host $File
}
}
###this part doesn't work
foreach($CurrentFolder in $AllFolders)
{
# Set the FolderRelativePath by removing the path of the folder supplied
# by the operator from the fullname of the folder
$FolderRelativePath = ($CurrentFolder.FullName).Substring($Folder.Length)
$FileSource = $Folder + $FolderRelativePath
$FilesInFolder = Get-ChildItem -Path $FileSource | ? {$_.psIsContainer -eq $False}
# For each file in the source folder being evaluated, call the UploadFile
# function to upload the file to the appropriate location
Foreach ($File in ($FilesInFolder))
{
Write-Host $File
if($Global:successfullymigrated -contains $File){
Write-Host $File
}
}
}
My code above is supposed to go through a file structure and checks to see if any of the file names are in the array (which is an array of strings with file names in them). My code works for the root files, prints out all the files that are in the array but when we get to checking the files in the other folders beyond the root it doesn't work. Even though it outputs the files that are in the file structure. I am completely stuck.
Forgive me if I have misunderstood but I read this
My code above is supposed to go through a file structure and checks to see if any of the file names are in the array
And interpreted that as you are just looking for file paths for files that match exactly a list of names you provide.
So I have this sample which should do just that.
$Global:successfullymigrated = #("template.txt","winmail.dat")
$folder = "C:\temp"
Get-ChildItem $folder -recurse | Where-Object{$Global:successfullymigrated -contains $_.Name -and !$_.psIsContainer} | Select-Object -ExpandProperty FullName
You should be able to incorporate this into your own code. It outputs the full paths to the matching files. The example I have outputs file from root and substructure.
C:\temp\winmail.dat
C:\temp\docs\template.txt
!$_.psIsContainer is to ensure that we do not get folders returned in our results. If you have PowerShell 3.0 or above then that can be replaced by the -File switch of Get-ChildItem

Powershell Filesize and Extension statistics after Get-ChildItem

what i do is to search files and write some of them with their absoulte path in a file.
now after this searching i want some statistics, like extensions, filesize...
So i need to read the file.txt and get these informations and after all are done, it should show the statistic. It doesnt work yet...
I think i have to store the information in arrays so i can group them later.
$directory="d:\file.txt"
get-content $directory|foreach {
MISSING PART?!
Get-ChildItem -Path $_ |
#Get only files
Where-Object { !$_.PSIsContainer } |
#Group by extension
Group-Object Extension |
#Get data
Select-Object #{n="Extension";e={$_.Name -replace '^\.'}}, #{n="Size (MB)";e={[math]::Round((($_.Group | Measure-Object Length -Sum).Sum / 1MB), 2)}}, Count}
do you have any idea? Thanks
I see you got this code from Determine recursively both COUNT and SUM of all extensions in a folder .
I'm guessing you are modifying it so that instead of a path, you can do different locations based on what is in the text file. In that case, this works:
#Get all items
Get-ChildItem -Path (Get-content C:\Users\krla226\Desktop\file.txt) |
#Get only files
Where-Object { !$_.PSIsContainer } |
#Group by extension
Group-Object Extension |
#Get data
Select-Object #{n="Extension";e={$_.Name -replace '^\.'}}, #{n="Size (MB)";e={[math]::Round((($_.Group | Measure-Object Length -Sum).Sum / 1MB), 2)}}, Count
All I changed from the answer on the other post was instead of a directory, I used Get-Content to pull the files paths from the text file.

Resources