BaseName for FileInfo objects

  • Comments 8

<Edited to add categories>
In our active, responsive, and useful newsgroup Microsoft.Public.Windows.PowerShell (SELL SELL SELL :-) ),  MVP Alex Angelopoulos recented posted the following:

Although file extension changing is a common technique in administrative
tasks, the System.IO.FileInfo class does not provide a direct Basename
property and neither does PowerShell.

This is useful enough that I believe it should be added to PS typedata. It
can  be done with a simple ScriptProperty, as shown below:

      $this.Name.Remove($this.Name.Length - $this.Extension.Length);

Alex posted this as a feature request and asked people to comment & vote on it at:

Alex's point is very timely in that we were just discussing this yesterday (Actually Alex tends to do that a lot, I wonder if my office is bugged.  Hmmmm.).  Anyway, we were talking about the possibility of adding this as an operator and then maybe having user-define operators.  Of course my initial reaction was - let's get this into V1.0 but we at a point in the project where we need to stop making changes to ensure the stability of the codebase.  (I suspect that our GPM Hilal has secretly purchased a roll of duct-tape for use the next time someone suggests adding a feature to V1.0. )

So what is great is that this is EXACTLY the situation we designed Windows PowerShell to address.  I've always HATED the conversation where a customer tells me what they need and then I have to say, "Got it, we'll add that.  Just hang in there a couple more years and we'll get you what you need."  We designed the system to address this (As you can see from the mention of user-defined operators, we continue to think about how to do a better job of this).  You can take the XML that Alex provided above and include it into your own My.Types.ps1xml (this process is describe reasonably well in ). 

I did this and now I can do the following:

PS> dir m* |ft name,basename -auto

Name                          Basename
----                          --------
mines.ps1                     mines
MonadScripting-HandsOnLab.doc MonadScripting-HandsOnLab
mow.types.ps1xml              mow.types
msh.msc                       msh
MSH.xshd                      MSH
MSH.xshd.1                    MSH.xshd
MSH.xshd.orig                 MSH.xshd
MSNSearchService.cs           MSNSearchService
MSNSearchService.dll          MSNSearchService
my.format.ps1xml              my.format
my.TaskTypes.ps1xml           my.TaskTypes
my.types.ps1xml               my.types
my.types2.ps1xml              my.types2
my1.format.ps1xml             my1.format
MyKnowledge.ps1               MyKnowledge
MyTabExpansion.ps1            MyTabExpansion

 So - we'll almost certainly do something similar to this in V2.0 (maybe V1.1) but you don't have to wait for us - you can have this function today.  Now just be aware of one thing - name collisions.  If you think about it, when we get around to it, if we decide to add this function to the type (as opposed to creating an operator for it), we'll almost certainly call it "BASENAME".  If you've already define your own property called BASENAME, there will be a collision (we use Casino rules on name collision [House wins on a tie]).  So you might consider calling it something unique. 

We should probably promulgate a naming convention for user-defined extensions.  I'd love to get input on that topic so please post that as comments to this blog. 

Jeffrey Snover
Windows PowerShell Architect

PSMDTAG:PHILOSOPHY: Provide mechanisms that the community can solve problems without waiting till the next release cycle.

Leave a Comment
  • Please add 4 and 2 and type the answer here:
  • Post
  • I agree.  If we can add it as a type that should be good for now.  Perhaps the typing that may be included in future releases shouyld be mediated by the PS Team.  A standard for adding types and documenting them so that when they are included in the release nothing will break.

    I would much rather see an AD provider take shape. While we can use AD through NET Framework or COM it would be far better to have a full PS provider for ADSI.

    How has Exchange managed to survive without an ADSI provider?  Are they building all of it into the Exchange provider?
  • After some volleying with Jacques Barathon, there's a slightly improved version of the code block which correctly handles files which have no extension or names that begin with a period:

    if ( ($this.extension.length -gt 0)
       -and ($this.extension.length -lt this.Name.length) )
       $this.Name.Remove($this.Name.Length - $this.Extension.Length)
  • Regarding a naming convention, you probably already know that I'm not a fan of "My." anything. Besides the customized types.ps1xml I use is located in the PSConfiguration folder.  I think this is where all customization files should go.  I don't think it is a good idea to have folks place customized files in PowerShell's install dir.  On Vista, depending on how you try to write to the Program Files dir the modification may or may not get virtualized.
  • I think that 'User' would be an appropriate prefix for all user-defined extensions.

    This avoids the overused and inappropreate use of 'My' and replaces it with an accurate and descriptive prefix.
  • this is nifty! love the user-extensibility of powerShell. Heck i love everything about it.

    got any advice/ideas about handling for: "cascading file types".

    say, your example file "MSH.xshd.orig" above --well under a 'cascading file types' scenario, this could be opened/viewed/(etc) by either:
     1. the apps that handle the 'xshd' extension
     2.  the apps that handle the 'orig' extension {pretending this is a genuine file type}

    what sort of support could ps offer for this cascading file types model?

    currently i'm thinking of just doing up a windows context menu enhancement for it... but now i see that powerShell could offer support too.

    more about it here:


  • RE: Cascading file types

    What you could do in this case is to have a ScriptMethod that you call to examine the object and dynamically add properties to itself.
    Add the following ScriptMethod to the FileInfo Type extension and you'll be able to do the example below.  You just add your own logic:

       <ScriptMethod>       <Name>AddCascadingFileTypes</Name>
    $basename,$extensions = $this.Name.Split(".")
    foreach ($e in $extensions)
      $this |Add-Member -type NoteProperty -Name ("ADDEDPROPERTY"+$e) -value $e

    PS> dir a.b*

       Directory: Microsoft.PowerShell.Core\FileSystem::C:\Temp

    Mode                LastWriteTime     Length Name
    ----                -------------     ------ ----
    -a---         7/13/2006   9:17 PM      17432 a.b.c.d.e.f.g

    PS> $x=(dir a.b*)
    PS> $x.AddCascadingFileTypes()
    PS> $x |fl a*

    Attributes     : Archive

    Jeffrey Snover [MSFT]
    Windows PowerShell/Aspen Architect
    Visit the Windows PowerShell Team blog at:
    Visit the Windows PowerShell ScriptCenter at:
  • PingBack from

Page 1 of 1 (8 items)

BaseName for FileInfo objects