Reputation: 218
I am new to Powershell and am unable to navigate to specific directories. I know where the directory is, but the command below doesn't work when I try to navigate to the directory.
Get-ChildItem -Directory | Select-Object -Last 1
I then want to Set-Location
to that but I can't figure out how to call it with the output of the above.
I was trying something like:
Get-ChildItem -Directory | Select-Object -Last 1
Set-Variable -Name "Dir" -Value { Get-ChildItem -Directory | Select-Object -Last 1 }
Set-Location -Path $Dir
but that doesn't work at all. Any pointers?
Upvotes: 0
Views: 1627
Reputation: 437131
There's good information in the comments, let me try to summarize and complement them:
{ ... }
is a script block literal in PowerShell: a reusable piece of code to be invoked later with &
, the call operator; that is, what's inside the curly braces is not executed right away.
Given that you want the execute and return the output from a command as the argument to another command, use ()
, the grouping operator[1].
Set-Variable -Name Dir -Value (Get-ChildItem -Directory | Select-Object -Last 1)
However, there is rarely a need to use the Set-Variable
cmdlet, given that simple assignments - $Dir = ...
work too, in which case you don't even need the parentheses:
$Dir = Get-ChildItem -Directory | Select-Object -Last 1
Of course, just like you can pass an (...)
expression to Set-Variable
, you can pass it to Set-Location
directly, in which case you don't need an intermediate variable at all (parameter -Path
is positionally implied):
Set-Location (Get-ChildItem -Directory | Select-Object -Last 1)
You can make this more concise by directly indexing the Get-ChildItem
call's output[2]; [-1]
refers to the last array element (output object):
Set-Location (Get-ChildItem -Directory)[-1]
The alternative is to use the pipeline (see about_Pipelines
):
Get-ChildItem -Directory | Select-Object -Last 1 | Set-Location
Note that there are subtle differences between the last 3 commands in the event that no subdirectories exist in the current directory (meaning that Get-ChildItem -Directory
produces no output):
Set-Location (Get-ChildItem -Directory | Select-Object -Last 1)
will report an error, because you're then effectively passing $null
as the -Path
argument.
Set-Location (Get-ChildItem -Directory)[-1]
will also report an error, because you cannot apply an index to a $null
value.
Get-ChildItem -Directory | Select-Object -Last 1 | Set-Location
, by contrast, will be a no-op, because Set-Location
effectively won't be invoked at all, due to not receiving input via the pipeline.
If not having subdirectories is an unexpected condition, you can force the script to abort by adding -ErrorAction Stop
to one of the first two commands - see about_CommonParameters
.
[1] While $(...)
, the subexpression operator, works too, it's usually not necessary - see this answer.
[2] Note that doing so means that all output from the Get-ChildItem
call is then collected in memory first, but that is unlikely to be a problem in this case. See this answer for more information.
Upvotes: 3