2

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

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
Dominik
  • 135
  • 1
  • 7
  • 5
    Pipe the newly-created container to `Set-Location`: `mkdir mydir | cd`. Otherwise, does this answer your question? [Create new directory and navigate into it (Windows CMD)](https://stackoverflow.com/questions/51343185/create-new-directory-and-navigate-into-it-windows-cmd) or [Combining two shell commands into a single command](https://stackoverflow.com/q/5924646/150605) – Lance U. Matthews Aug 14 '22 at 18:00
  • 3
    `mkdir mydir3 | cd -Path { $_ }` works, too, using [delay-binding](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_script_blocks#using-delay-bind-script-blocks-with-parameters) and doesn't change to using the provider path. – Lance U. Matthews Aug 14 '22 at 18:09
  • 1
    Another one that doesn't change to using provider path: `mkdir mydir | % fullname | cd` – zett42 Aug 14 '22 at 20:11

1 Answers1

4

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
  • Nicely done. As for `mkdir mydir | cd` unexpectedly showing the provider prefix in the prompt string / in `$PWD`: this should be considered a _bug_: see [GitHub issue #10522](https://github.com/PowerShell/PowerShell/issues/10522). Maybe worth noting, as an aside: on Unix-like platforms, `mkdir` defers to the platform native utility of that name, which doesn't produce output; there, `New-Item -TypeDirectory ...` is required instead. – mklement0 Aug 16 '22 at 22:41