Share via


how to handle directories with special characters in their name

Question

Thursday, September 11, 2014 2:22 AM

I can't figure out how to recode the second clause of this function to handle directories like one named "[]"

function Get-DiskUsage {

  # parse and pray (but it does accept directory []
  # 

  dir |
    ? { $_.psIsContainer } |
      % {
          $size = ((@(cmd /c dir /s $_.name)[-2])[25..39] -join '')
          if ($size[14] -eq ' ') {
            $size = ' ' + ((@(cmd /c dir /s $_.name)[-2])[25..38] -join '')
           }
          $name = $_.name
          ' ' + $size + ' ' + $name
        }

  # object oriented, but it does not accept directory []
  # 

  Get-ChildItem -Directory |
      Select-Object @{ Name="Size";
          Expression={ ($_ | Get-ChildItem -Recurse |
              Measure-Object -Sum Length).Sum + 0 } },
          Name

 }

All replies (9)

Thursday, September 11, 2014 4:49 AM âś…Answered | 1 vote

I was going to try to write a slicker expression to handle other special characters that are valid in directory names, but those seem to be the only ones that cause a problem.

PS C:\temp>   Get-ChildItem -Directory |
>>       Select-Object @{ Name="Size";
>>           Expression={ ($_ -replace "\","``[" -replace "\","``]" | Get-ChildItem -Recurse |
>>               Measure-Object -Sum Length).Sum + 0 } },
>>           Name | ft -autosize
>>

    Size Name
   
       0 bl
       0 bl#ah
       0 bl$ah
       0 bl%ah
       0 bl&ah
       0 bl)(ah
       0 bl+ah
       0 bl@ah
       0 bl^ah
       0 bl`ah
       0 d 'bl'ah
14514381 FromIBMKey
    8017 Misc
     192 test[]

I hope this post has helped!


Thursday, September 11, 2014 2:42 AM

It worked ok for me:

PS C:\temp>   Get-ChildItem -Directory |
>>       Select-Object @{ Name="Size";
>>           Expression={ ($_ | Get-ChildItem -Recurse |
>>               Measure-Object -Sum Length).Sum + 0 } },
>>           Name | ft -autosize
>>

    Size Name
   
14514381 FromIBMKey
    8017 Misc
         test[]

Are you getting some kind of error?

I hope this post has helped!


Thursday, September 11, 2014 2:55 AM

No error.  I just don't get a computed number of bytes for the files inside my directory named  [] 

I see that you don't get a byte count for your test[] directory.


Thursday, September 11, 2014 3:22 AM

Add -LiteralPath switch to your Get-Childitem

 Expression={ ($_ | Get-ChildItem -Recurse -LiteralPath |

[string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


Thursday, September 11, 2014 4:16 AM | 1 vote

You're right.  There was nothing in the directory so I didn't even think of that.

I tried with -LiteralPath and got a different result:

PS C:\temp>   Get-ChildItem -Directory |
>>       Select-Object @{ Name="Size";
>>           Expression={ ($_ | Get-ChildItem -Recurse -LiteralPath |
>>               Measure-Object -Sum Length).Sum + 0 } },
>>           Name
>>

Size                                                        Name
                                                       
                                                            FromIBMKey
                                                            Misc
                                                            test[]

This seems like a hack but it works:

Expression={ ($_ -replace "\[","``[" -replace "\]","``]" | Get-ChildItem -Recurse |

I hope this post has helped!


Thursday, September 11, 2014 4:18 AM | 1 vote

If I cd and tab-autocomplete to that directory Powershell does the same thing, which is what gave me the idea:

PS C:\temp> cd '.\test`[`]'

I hope this post has helped!


Thursday, September 11, 2014 2:05 PM | 1 vote

Thanks so much!  Below is a before and after with a bit of tidying up that shows exactly what you changed to make it work.

  
  # object oriented (but cannot handle directories with [ and ] in the name)
  # 
  
  Get-ChildItem -Directory |
    Select-Object @{
      Name='Size';
      Expression={
        ( $_ |
          Get-ChildItem -Recurse |
          Measure-Object -Sum Length).Sum + 0 } 
        },Name 
  

  
  # object oriented (with special treatment of [ and ] in directoey names)
  # 

  Get-ChildItem -Directory |
    Select-Object @{
      Name='Size';
      Expression={
        ( $_ -replace '\[','`[' -replace '\]','`]' |
          Get-ChildItem -Recurse |
          Measure-Object -Sum Length).Sum + 0 } 
        },Name 

Thursday, September 11, 2014 2:09 PM

Adding -LiteralPath seems an intuitive solution, but it does not work.   Perhaps there is a bug in PowerShell's Get-ChildItem cmdlet's implementation.


Friday, September 12, 2014 2:18 AM | 1 vote

Here is the function with additional functionality to count bytes in the files in the directory itself as well as subdirectories, and accept an optional argument to specify the target directory.  I wish there was a better way
to do this without modifying and later restoring $pwd

function Get-DiskUsage {
  
#
# Discovers how much space is allocated in the directories at and below
#    the current directory
#
# Inspired by a version from Windows PowerShell Cookbook by Lee Holmes
#   http://www.leeholmes.com/guide
#
# The change to parse ] and [ correctly in a directory name was created by Rhys W Edwards
#   http://social.technet.microsoft.com/Forums/en-US/f4f0a133-8c4d-4089-8047-274dbc03567b
#
  
# if there is an argument, then validate it as an actual directory and set $pwd to it

  if ($args.length -gt 0) {
    if ((Test-Path -Path $args[0] -PathType Container) -eq $False) {
      return
     }
    $pwdsave = $pwd
    cd $args[0]
   }
  
# 
# count of bytes in the files in the directory itself
#
 
  (Get-ChildItem | Measure-Object -property length -sum) |
     Select-Object @{Name='Size';Expression={$_.Sum}},@{Name='Name';Expression={$pwd}}
  
#
# count of bytes in the files in the subdirectories
#
  
  Get-ChildItem -Directory |
    Select-Object @{
      Name='Size';
      Expression={
        ( $_ -replace '\[','`[' -replace '\]','`]' |
          Get-ChildItem -Recurse |
          Measure-Object -Sum Length).Sum + 0 } 
        },Name 
  
# restore $pwd is needed
  
  if ($args.length -gt 0) {
    cd $pwdsave
   }
  
 }