header image

Archive for File System

Count of files in a folder

Posted by: | February 18, 2012 | 1 Comment |

I was recently left a comment of a post


asking about the how to get the count of files in a folder

There are a number of solutions including dropping back to the FileSystem object from VBscript

If we want just a PowerShell option

function filecount {            
param (            
 if (-not (Test-Path $path)){Throw "Path: $path not found"}            
 $count = 0            
 $count = Get-ChildItem -Path $path |             
          where {!$_.PSIsContainer} |             
          Measure-Object |            
          select -ExpandProperty count            
 Get-Item -Path $path |             
 select PSDrive,             
 @{N="Parent"; E={($_.PSParentPath -split "FileSystem::")[1]}},            
 @{N="FileCount"; E={$count}}            
 Get-ChildItem -Path $path |             
 where {$_.PSIsContainer} |            
 foreach {            
   filecount $($_.Fullname)            
filecount "c:\scripts"

Supply a path to the top level folder for the filecount function

It will test if the folder exists & complain if it doesn’t.

We can then count the files in the folder using PSISContainer to filter out any subfolders and measure-object to perform the count.

Get-item is used on the path and piped into select where we split out the parent path and add the file count (that count be done with add-member as well

Get-ChildItem is used on the path and only folders are passed. The path of each subfolder is passed to the filecount function. 

A function calling itself like this known as recursion

under: File System, PowerShell Basics

A question on the forum asked about setting creation date on folders after they have been copied to match the source folder.

I created a source folder with three folders and modified the creation dates

Set-ItemProperty -Path c:\testsource\folder1 -Name CreationTime -Value ((get-date).adddays(-90))
Set-ItemProperty -Path c:\testsource\folder2 -Name CreationTime -Value ((get-date).adddays(-127))
Set-ItemProperty -Path c:\testsource\folder3 -Name CreationTime -Value ((get-date).adddays(-192))


I then created a file

dir c:\scripts |out-file -FilePath test.txt

and copied it into each folder


The copy of the folders and their contents is achieved like this

Copy-Item -Path c:\testsource\* -Destination c:\testtarget -Force –Recurse


Our source looks like this

PS> Get-ChildItem -Path c:\testsource | where {$_.PSIsContainer} | ft  Fullname, CreationTime -a

FullName                             CreationTime
——–                                    ————
C:\testsource\Folder1   13/11/2011 11:26:35
C:\testsource\Folder2   07/10/2011 11:27:12
C:\testsource\Folder3   03/08/2011 11:27:27


and the target looks like this

PS> Get-ChildItem -Path c:\testtarget | where {$_.PSIsContainer} | ft  Fullname, CreationTime -a

FullName                           CreationTime
——–                                  ————
C:\testtarget\Folder1   11/02/2012 11:34:25
C:\testtarget\Folder2   11/02/2012 11:34:25
C:\testtarget\Folder3   11/02/2012 11:34:25


So our job is to change the creationtime property on the target folders


Get-ChildItem -Path c:\testsource -Recurse |             
where {$_.PSIsContainer} |            
foreach {            
 $newfolder = $_.Fullname -replace "Testsource", "Testtarget"            
 Set-ItemProperty -Path $newfolder -Name CreationTime -Value $($_.CreationTime)            


Just loop through the source folders – change the path to match the target and set the CreationTime


We can then test the results

PS> Get-ChildItem -Path c:\testtarget | where {$_.PSIsContainer} | ft  Fullname, CreationTime -a

FullName                           CreationTime

——–                                  ————

C:\testtarget\Folder1   13/11/2011 11:26:35

C:\testtarget\Folder2   07/10/2011 11:27:12

C:\testtarget\Folder3   03/08/2011 11:27:27


Job done

under: File System, PowerShell Basics

A question in the forums wanted to get the date a folder was changed on their domain controllers. This is one way to do it

$folder = "Common Files"            
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() |             
select -ExpandProperty DomainControllers |             
foreach {            
 $dc = $_.Name            
 if (Test-Path -Path "\\$dc\c$\Program Files (x86)\$folder") {            
  $data =  Get-Item "\\$dc\c$\Program Files (x86)\$folder" | select Fullname, LastWriteTime            
 else {            
  $data =  Get-Item "\\$dc\c$\Program Files\$folder" | select Fullname, LastWriteTime            
 $data | Add-Member -MemberType NoteProperty -Name Server -Value $dc -PassThru            

In this case the folder would only be in the 32 bit program files folder so see if “program files (x86)” exists – if so its 64 bit machine & we want that folder. if not we revert to “program files”

Final act is to add the computer name as a parameter – that could also be done as a calculated field in select

under: File System, PowerShell Basics

Following on from the previous post I was asked if the bit where we set the case on the file names and extension could be done in a select statement.

Simple answer is yes

Get-ChildItem |                        
where {-not $_.PSIsContainer} |                        
sort Fullname |                        
select @{N="FullName"; E={$($_.Fullname.ToUpper())}},                         
@{N="Extension"; E={$($_.Extension.ToLower())}},             
Length, LastWriteTime |            
Format-Table -Autosize

Calculated fields can be used in Format-Table and Select-Object cmdlets

I didn’t mention previously – N is short for Name and E is short for Expression above

under: File System, PowerShell Basics

Formatting file listings

Posted by: | December 29, 2011 | No Comment |

A question was left asking about displaying a file listing with the full name in upper case and the extension in lower case. Its one line of PowerShell

Get-ChildItem |            
where {-not $_.PSIsContainer} |            
sort Fullname |            
Format-Table @{N="FullName"; E={$($_.Fullname.ToUpper())}},             
@{N="Extension"; E={$($_.Extension.ToLower())}}, Length, LastWriteTime -Autosize
under: File System, PowerShell Basics

Split-Path & UNC

Posted by: | September 19, 2011 | No Comment |

split-path works with with UNC paths as well as normal paths


PS> $path = "\\UNCserver\TFSBuilds\componenet\v11.1\XS11.1\XS11.1_11.1.0.35"
PS> Split-Path -Path $path -Parent


PS> Split-Path -Path (get-location) -Parent

under: File System

Removing empty folders seems to be a question that crops up on a regular basis. The problem is determining if a folder is empty:

  • it could have subfolders
  • it could have zero length files

Both of these cases would register as empty if all we checked was get-childitem and summed the file sizes especially if subfolders are ignored.

One way to remove empty folders is to use the Scripting Object.  Yes back to VBScript days. Those old COM objects have some mighty fine functionality that we might as well use while its there.

$path = "c:\test"            
$fso = New-Object -ComObject "Scripting.FileSystemObject"            
$folder = $fso.GetFolder($path)            
foreach ($subfolder in $folder.SubFolders){            
 if (($subfolder.Files | Measure-Object).Count -gt 0){continue}            
 if (($subFolders.SubFolders  | Measure-Object).Count -gt 0){continue}            
 if ($subfolder.Size -eq 0 ){Remove-Item -Path $($subfolder.Path) -Force -WhatIf}            

Create a Scripting.FileSystemObject

Get the folder and for each sub folder check the files and subfolders if either are non zero then ignore (go back to top of loop)

if the sub folder size reports as zero then delete it.  I’ve added the whatif parameter so I can easily test.

This only tests one level of subfolders – if we want them all then its time for some recursion

function remove-emptyfolder {            
 param ($folder)            
 foreach ($subfolder in $folder.SubFolders){            
 $notempty = $false            
 if (($subfolder.Files | Measure-Object).Count -gt 0){$notempty = $true}            
 if (($subFolders.SubFolders  | Measure-Object).Count -gt 0){$notempty = $true}            
 if ($subfolder.Size -eq 0 -and !$notempty){            
   Remove-Item -Path $($subfolder.Path) -Force -WhatIf            
 else {            
  remove-emptyfolder $subfolder            
$path = "c:\test"            
$fso = New-Object -ComObject "Scripting.FileSystemObject"            
$folder = $fso.GetFolder($path)            
remove-emptyfolder $folder


This is based on the previous script except the folder analysis and deletion is in a folder that calls itself if the current folder has subfolders. The test for files and subfolders are used to set a boolean to help determine whether to delete or perform more analysis

under: File System

Folder and file names

Posted by: | August 11, 2011 | No Comment |

Saw a question in the forums – running Get-ChildItem and wanted the folder containing the file.  Could split PSParent and pick the last element or can use a calculated field

Get-ChildItem -Path c:\test -Recurse |
select FullName, @{N="Folder"; E={Split-Path -Path (Split-Path -Path $_.fullname -Parent) -Leaf  }}

use split-path to get the container and put that into split-path to get the leaf i.e. the last folder in the path.

Jobs a good un!

under: File System

Modifying favourites

Posted by: | June 27, 2011 | No Comment |

if we use our get-favourite function to look at the content of favourite files


get-favourite | select -f 5 | foreach{""; get-content -Path $_.path}


we see this sort of structure



Not all files have the BASEURL or [DEFAULT] section but they do have the [InternetShortcut]. The other bit we need to consider is the iconfile

We can put together a function to change the URL in a favourite

function set-favourite{             
$lines = Get-Content -Path $path            
$i = 0            
foreach($line in $lines) {            
 if ($line.StartsWith("BASEURL") ){$lines[$i] = "BASEURL=$url"}            
 if ($line.StartsWith("URL") ){$lines[$i] = "URL=$url"}            
 if ($line.StartsWith("IconFile") ){$lines[$i] = "IconFile=$url/favicon.ico"}            
Set-Content -Value $lines -Path $path            
Changes URL of a favourite

Changes URL of a favourite

get-favourite | where {$_.Name -like "google"} | set-favourite -url "www.bing.com"


The function can be used as follows

get-favourite | where {$_.Name -like "google"} | set-favourite -url www.bing.com


Next job is to create a favourite from scratch

under: File System, PowerShellV2

Viewing favourites

Posted by: | June 24, 2011 | No Comment |

I recently copied my favourites between machines which started me thinking about viewing favourites. Like many people I have generated a lot of favourites over the years – do I really need them all. Don’t know because I don’t know what they are.  Its easy to correct that

$favs = New-Object -ComObject Shell.Application            
Get-ChildItem -Path $favs.NameSpace(0x6).Self.Path -Recurse |            
where {-not $_.PSIsContainer} |            
foreach {            
 $fav = New-Object -TypeName PSObject -Property @{            
  Name = $_.BaseName             
 Get-Content -Path $_.FullName | foreach {            
  if ($_.StartsWith("URL=")) {            
   $fav | Add-Member -MemberType NoteProperty -Name URL -Value $_.Replace("URL=","")}            

The script use the Shell COM object to access the favourites special folder. We then iterate through the favourites and get the content of each favourite. These are just text files so we can pick out the URL. An object is created to hold the favourite name and URL and then displayed

under: COM, File System, PowerShellV2

« Newer Posts - Older Posts »