Search code examples
powershellparametersmkdircdautomatic-variable

Equivalent of "&& cd $_" in Powershell


With bash I can create a directory and immediately enter it with mkdir mydir && cd $_. Is there a powershell equivalent of $_?


Solution

  • There are a few ways to do this. Remember that cd is an alias for the Set-Location cmdlet.

    Pipe the newly-created directory to cd

    PS X:\> mkdir mydir | cd
    PS Microsoft.PowerShell.Core\FileSystem::X:\mydir>
    

    Notice that after running the command the current location uses the directory's provider path.

    If you don't like the visual clutter, you could instead...

    Pass the newly-created directory to -Path

    Via a delay-bind script block
    PS X:\> mkdir mydir | cd -Path { $_ }
    PS X:\mydir>
    

    -Path must be specified as a named parameter for this to work.

    Via a direct parameter value
    PS X:\> cd -Path (mkdir mydir)
    PS X:\mydir>
    

    ...or simply...

    PS X:\> cd (mkdir mydir)
    PS X:\mydir>
    

    Pipe the newly-created directory's FullName property to cd

    In a comment @zett42 suggests...

    PS X:\> mkdir mydir | % FullName | cd
    PS X:\mydir>
    

    ...which is a shorter way of writing...

    PS X:\> mkdir mydir | ForEach-Object -MemberName 'FullName' | cd
    PS X:\mydir>
    

    ...and works the same as...

    PS X:\> mkdir mydir | Select-Object -ExpandProperty 'FullName' | cd
    PS X:\mydir>
    

    ...and much the same as...

    PS X:\> (mkdir mydir).FullName | cd
    PS X:\mydir>
    

    Use ForEach-Object to pass the $_ automatic variable to both mkdir and cd

    In this answer to Create new directory and navigate into it (Windows CMD) @Shenk suggests...

    PS X:\> echo mydir | % { mkdir $_; cd $_ }
    
    
        Directory: X:\
    
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    d-----         8/15/2022   2:35 PM                mydir
    
    
    PS X:\mydir>
    

    ...which can be simplified to...

    'mydir' | % { mkdir $_; cd $_ }
    

    ...and is much the same as...

    $name = 'mydir'; mkdir $name; cd $name
    
    Considerations

    Notice that, unlike the other solutions, because the output of mkdir is not captured by a variable, pipeline, parameter, etc. it is written to the console. If this is undesirable, you'll need to explictly suppress that output with something like...

    'mydir' | % { mkdir $_; cd $_ } | Out-Null
    

    ...or...

    'mydir' | % { mkdir $_; cd $_ } > $null
    

    Also, if mkdir fails then cd could be unconditionally executed, anyways. For example, this...

    PS X:\> 'Directory name with invalid characters ?*' | % { mkdir $_; cd $_ }
    mkdir : Illegal characters in path.
    At line:1 char:51
    + 'Directory name with invalid characters ?*' | % { mkdir $_; cd $_ }
    +                                                   ~~~~~~~~
        + CategoryInfo          : InvalidArgument: (X:\Directory na...d characters ?*:String) [New-Item], ArgumentExceptio
       n
        + FullyQualifiedErrorId : CreateDirectoryArgumentError,Microsoft.PowerShell.Commands.NewItemCommand
    
    cd : Cannot find path 'Directory name with invalid characters ?*' because it does not exist.
    At line:1 char:61
    + 'Directory name with invalid characters ?*' | % { mkdir $_; cd $_ }
    +                                                             ~~~~~
        + CategoryInfo          : ObjectNotFound: (Directory name ...d characters ?*:String) [Set-Location], ItemNotFoundE
       xception
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
    
    PS X:\>
    

    ...produces two errors, not one, after the directory could not be created due to an invalid name, and this...

    PS X:\> 'Directory name that already exists' | % { mkdir $_; cd $_ }
    mkdir : An item with the specified name X:\Directory name that already exists already exists.
    At line:1 char:44
    + 'Directory name that already exists' | % { mkdir $_; cd $_ }
    +                                            ~~~~~~~~
        + CategoryInfo          : ResourceExists: (X:\Directory name that already exists:String) [New-Item], IOException
        + FullyQualifiedErrorId : DirectoryExist,Microsoft.PowerShell.Commands.NewItemCommand
    
    PS X:\Directory name that already exists>
    

    ...changes the current directory even after mkdir failed to create a directory that already exists.