PowerShell: Count files in a given name directory and subfolders - powershell

I need to count files inside given folders
example:
Folder A
Folder B
Folder C
For each folder I need to count how many files there are, and at the end sum the total.
What is the best to way to do this?

try this :
$DirList=#('C:\temp\BATCHHISTOCRE', 'C:\temp\tmp', 'C:\temp\444')
$DirList | %{
[pscustomobject]#{
Dirname=$_
NbFile=(Get-ChildItem -Path $_ -File).Count # Add -recurse if you want all tree into your dir
}
}

Tagging on to #Esperento57:, helpful answer.
Yeppers, it does work, but it will also error off if the folder path has no files; whereas using Measure-Object in the mix, can address that.
$DirList = #('D:\Temp\AddressFiles',
'D:\Temp\BonoboGitServer',
'D:\Temp\Book'
)
$DirList |
ForEach-Object {
[pscustomobject]#{
Dirname = $PSItem
NbFile = (Get-ChildItem -Path $PSItem -File).Count
}
}
# Results
<#
Dirname NbFile
------- ------
D:\Temp\AddressFiles 3
The property 'Count' cannot be found on this object. Verify that the property exists.
At line:8 char:5
+ [pscustomobject]#{
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
D:\Temp\Book 4
#>
Whereas using the Measure-Object cmdlet, addresses the issue...
$DirList = #('D:\Temp\AddressFiles',
'D:\Temp\BonoboGitServer',
'D:\Temp\Book'
)
$DirList |
ForEach-Object {
[pscustomobject]#{
Dirname = $PSItem
NbFile = (Get-ChildItem -Path $PSItem -File |
Measure-Object).Count
}
}
# Results
<#
Dirname NbFile
------- ------
D:\Temp\AddressFiles 3
D:\Temp\BonoboGitServer 0
D:\Temp\Book 4
#>

Related

storing filename and path in variable to use with Copy-Item

I'm trying to write a script to find the most recent .bak in a certain directory and copy the file to another location. When I use Get-ChildItem the file name isn't enlcosed in single quotes so when i try to copy it Copy-Item cant find it. ( I think)
$dir = 'E:\Backups\'
$dest = 'F:\'
$filename = Get-ChildItem -path $dir -filter *.bak | Sort-Object CreationTime -Descending | Select-Object -First 1 | select FullName | Format-Table -HideTableHeaders
echo #filename
copy-Item -path #filename -destination #dest
echo #filename returns E:\Backups\company.bak but i think need 'E:\Backups\company.bak' for it to work?
PS C:\Users\prodadmin> copy-Item -path #filename -destination #dest
Copy-Item : A positional parameter cannot be found that accepts argument 'Microsoft.PowerShell.Commands.Internal.Format.GroupStartData'.
At line:1 char:1
+ copy-Item -path #filename -destination #dest
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Copy-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
As above, typed it all in one go.
Get-ChildItem returns FileInfo (and also DirectoryInfo) objects.
By using select FullName you tell PowerShell to return an new object with one property called FullName and you lose the Name property.
Format-Table is a cmdlet used for display purposes only, so never use that on data you want to process further.
Lastly, you prefix the variables you have with # instead of $
Try
$dir = 'E:\Backups\'
$dest = 'F:\'
$file = Get-ChildItem -Path $dir -Filter '*.bak' -File | # do not return directories
Sort-Object CreationTime -Descending | # or did you mean LastWriteTime (=> last modified date) ?
Select-Object -First 1 # return just 1 FileInfo object
Write-Host "Found $($file.Name)" # write to console
Copy-Item -Path $file.FullName -Destination $dest

Powershell Select-Object how to get array of values

I am trying to delete contents of few folders.
What I have:
$Config = #{
InstallPath = 'C:\Program Files\App'
SubPaths = #('www\app1', 'www\app2', 'www\app3')
}
And here is the code to get contents:
$Config.SubPaths | Select-Object { Join-Path $Config.InstallPath $_ } | Get-ChildItem
But it doesn't work, because Get-ChildItem receives object like below:
#{ Join-Path $Config.InstallPath $_ =C:\Program Files\App\www\app1}
Error:
Get-ChildItem : Cannot find drive. A drive with the name '#{ Join-Path $Config.InstallPath $_ =C' does not exist.
At line:1 char:85
+ ... elect-Object { Join-Path $Config.InstallPath $_ } | Get-ChildItem
+ ~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (#{ Join-Path $C...stallPath $_ =D:String) [Get-ChildItem], DriveNotFoun
dException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
How can I convert result of Select-Object to simple array of strings? Or any other approach to make code better?
The results you are getting are because you made a new object with the the literal property Join-Path $Config.InstallPath $_. Instead...
$Config.SubPaths | ForEach-Object { Join-Path $Config.InstallPath $_ } | Get-ChildItem
You are not trying to select a property of a single subpath but generate a string from each of the SubPaths. Using Foreach-object instead to iterate over the collection should get you the results you are looking for.
While you could create custom objects and properties using calculated properties I figure this is not the direction you are going for. But to answer the question in the title you could have done this:
$Config.SubPaths |
Select-Object #{Name="Path";Expression={Join-Path $Config.InstallPath $_}} |
Get-ChildItem
Get-ChildItem should bind to the path property of the new object were are making

How to get a list of directories or 'none'?

With PowerShell I want to check a directory (full name in $PathOutput) if it contains other directories. If this path does not contain other directories, I want a variable $FailedTests to have the string 'none', otherwise the variable $FailedTests should contain every found directory (non-recursive), either in a different line, or comma-seperated, or whatever.
I have tried the following code:
$DirectoryInfo = Get-ChildItem $PathOutput | Measure-Object
if ($directoryInfo.Count -eq 0)
{
$FailedTests = "none"
} else {
$FailedTests = Get-ChildItem $PathOutput -Name -Attributes D | Measure-Object
}
but it generates the following error:
Get-ChildItem : A parameter cannot be found that matches parameter name 'attributes'.
At D:\Testing\Data\Powershell\LoadRunner\LRmain.ps1:52 char:62
+ $FailedTests = Get-ChildItem $PathOutput -Name -Attributes <<<< D | Measure-Object
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
I am using Powershell 2.0 on Windows Server 2008.
I would prefer a solution which uses Get-ChildItem or whetever only once.
The error is actually rather self-explanatory: Get-ChildItem (in PowerShell v2) doesn't have a parameter -Attributes. That parameter (as well as the parameter -Directory) was added with PowerShell v3. In PowerShell v2 you need to use a Where-Object filter for removing unwanted results, e.g. like this:
$DirectoryInfo = Get-ChildItem $PathOutput | Where-Object {
$_.Attributes -band [IO.FileAttributes]::Directory
}
or like this:
$DirectoryInfo = Get-ChildItem $PathOutput | Where-Object {
$_.GetType() -eq [IO.DirectoryInfo]
}
or (better) like this:
$DirectoryInfo = Get-ChildItem $PathOutput | Where-Object { $_.PSIsContainer }
You can output the folder list, or "none" if there weren't any, like this:
if ($DirectoryInfo) {
$DirectoryInfo | Select-Object -Expand FullName
} else {
'none'
}
because an empty result ($null) is interpreted as $false.
You could maybe do something like this? This way you also do not have to get the childitems twice.
$PathOutput = "C:\Users\David\Documents"
$childitem = Get-ChildItem $PathOutput | ?{ $_.PSIsContainer } | select fullname, name
if ($childitem.count -eq 0)
{
$FailedTests = "none"
}
else
{
$FailedTests = $childitem
}
$FailedTests

Get-ACL -Literalpath throws: illegal character in path

I have an arraylist of all folders and files where I want to get the ACL off.
Everything runs well in my Foreach loop.
But for one odd reason it throws:
Get-Acl : Illegal characters
+ CategoryInfo : NotSpecified: (:) [Get-Acl], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.GetAclCommand
When I run the get-acl manual with the 'faulty' path, I get the ACL.
My code is:
$ACL = get-acl -LiteralPath "$Path" | select -ExpandProperty access | select IdentityReference
$Result = Compare-Object -ReferenceObject $ACLListAccess -DifferenceObject $ACL -Property Access -PassThru
if ($Result.count -ne 0)
{
$ExplicitTest = get-acl -LiteralPath "$Path" | select -ExpandProperty access
if ($ExplicitTest.IsInherited.count -ne $ACLListAccessFull.count -and $ExplicitTest.IsInherited -Like "*False*")
{
$WrongFolders.Add($Path) | Out-Null
}
}
The Path with the 'illegal character' is
\mycompany.com\folders\Algemeen\Reme§ysen
Sorry, cannot repro your problem and comment does not allow me to paste this
D:\temp\a> get-acl .\aaa§bbb
Directory: D:\temp\a
Path Owner Access
---- ----- ------
aaa§bbb adil BUILTIN\Administrators Allow FullControl...
if you copy paste that character, do you also get 167?
C:\> [int][char]'§'
167

Powershell - Export Multiple CSV's into unique folders

I have been working on a PowerShell script for the better part of well a week or two. I've been able to get some parts of it working however I'm unable to fully get this automated.
I deal with a lot of CSV files on a daily basis, I have been tasked with uploading them into our software however sometimes they're too large to handle so I break them down based upon their "type" (it's a column in the CSV) and I export it to a single CSV per "type". I've been able to accomplish this with the following:
$file = gci -Filter "*.csv";
Import-Csv $file `
| Group-Object –Property “type” `
| Foreach-Object `
{
$path=$_.name+”.csv” ; $_.group `
| Export-Csv –Path $path –NoTypeInformation
}
So this works wonderfully, for each individual CSV. Unfortunately I don't have the time to do this for each individual CSV. Now I come to my other PowerShell script:
get-childitem -Filter "*.csv" `
| select-object basename `
| foreach-object{ $path=$_.basename+".csv" #iterate through files.
if(!(Test-Path -path $_.basename)) #If the folder of the file can't be found then it will attempt to create it.
{
New-Item $_.basename -type directory; $file=$_.basename+".csv";
Import-Csv $file `
| Group-Object -Property "Type" `
| Foreach-Object {
$path=$_.name+".csv"; $_.group `
| `
if(!(Test-Path -path $path2))
{
New-Item $path2 -type directory
Export-Csv -Path $path2 + "\" + $path -NoTypeInformation
}
else
{
"Failed on: " + $_.basename
#Export-Csv -Path $_.basename + "\" + $path -NoTypeInformation
}
}
}
else
{
Import-Csv $path `
| Group-Object -Property "Type" `
| Foreach-Object {$path=$_.basename+".csv" ; $_.group
if(Test-Path -path $._)
{
New-Item $path2 -type directory
Export-Csv -Path $path2 + "\" + $path -NoTypeInformation
}
#else
#{
Write-Host "Failed on: $_.basename"
#Export-Csv -Path $_.basename + "\" + $path -NoTypeInformation
#}
}
}
}
I just can't wrap my head around "why" this isn't working effectively. I have two conditionals. Is there a folder for the CSV? If no create one. I have to have another one because one of the "types" contains a \ which errors out if I don't have the folder, so I automatically try to create it. When I run the script I get the Path is null.
The Error is:
The term ' ' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or
if a path was included, verify that the path is correct and try again.
At C:\Users\c.burkinshaw\foldermake.ps1:11 char:26
+ | ` <<<<
+ CategoryInfo : ObjectNotFound: ( :String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Test-Path : Cannot bind argument to parameter 'Path' because it is null.
At C:\Users\c.burkinshaw\foldermake.ps1:12 char:45
+ if(!(Test-Path -path <<<< $path2))
+ CategoryInfo : InvalidData: (:) [Test-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand
Any help would be greatly appreciated, if you have questions please don't hesitate to ask.
You have not defined $path2 anywhere, so something like test-path -path $path2 will say path is null. And in one place you are using $._ which will again give errors.
Edit after question updated with error message:
Your error message also says the same
Test-Path : Cannot bind argument to parameter 'Path' because it is
null. At C:\Users\c.burkinshaw\foldermake.ps1:12 char:45
+ if(!(Test-Path -path <<<< $path2))
Also the other error is in:
$path=$_.name+".csv"; $_.group `
| `
what are you trying to do here with the $_.group?
It is not proper. You cannot do $_.group | and provide some if statement.
Other comments:
Why are using $_.basename and then appending .csv? You could have just used $_.name. Try to not use the select-object basename - I don't see the value.
Extract the common import-csv and export-csv part into a function.