I want to open [test].txt
in powershell, but when I press tab on keyboard, it autocompletes like this:
start '.\`[test`].txt'
and generates this error:
start: Could not run this command due to error: The system cannot find the file specified. At line: 1 character: 1 start '.`[test`].txt' ~~~~~~~~~~~~~~~~~~~~~~~~ CategoryInfo: InvalidOperation: (:) [Start-Process], InvalidOperationException FullQualifiedErrorId: InvalidOperationException, Microsoft.PowerShell.Commands.StartProcessCommand
I want to remove the backtick characters when I press tab. How can I do this?
CodePudding user response:
start
(an alias for Start-Process
) is really designed to launch executables or external commands.
For invoking the default shell handler associated with an arbitrary file, use Invoke-Item
instead!
In order to avoid PowerShell attempting to interpret [...]
as a wildcard pattern, use the -LiteralPath
parameter:
Invoke-Item -LiteralPath '.\[test].txt'
All item provider cmdlets (*-Item
, *-ChildItem
) supports literal path binding, so it's always the best/safer choice when you have an exact path.
CodePudding user response:
To complement Mathias R. Jessen's helpful answer.
What you're seeing is a limitation in PowerShell's tab-completion (up to at least PowerShell Core 7.2.0-preview.9):
You're tab-completing a value for the - positionally implied -
-FilePath
parameter of theStart-Process
cmdlet (start
is built-in alias for it).Since
-FilePath
only accepts literal (verbatim) file paths, not also wildcard patterns, tab-completion should result in.\[test].txt
, without the`
-escaping of wildcard-pattern metacharacters[
and]
.
By contrast, Invoke-Item
(whose built-in alias is ii
) does support wildcard patterns via its -Path
parameter - as well as literal (verbatim) paths via its -LiteralPath
parameter:
Since
-Path
is inInvoke-Item's
default parameter set and is the first positional parameter, the tab-completed value would have worked as-is had you usedInvoke-Item
rather thanStart-Process
:# OK with tab-completion: positionally binds to -Path Invoke-Item '.\`[test`].txt'
In fact, tab-completion is aware of when the argument at hand will be bound to a
-LiteralPath
parameter and then does not perform escaping:# OK with tab-completion: due to explicitly targeting -LiteralPath, # no escaping is performed. Invoke-Item -LiteralPath .\[test].txt
The above applies to all provider cmdlets, such as
Get-ChildItem
andGet-Content
(roughly speaking, they comprise the cmdlets that have the wordItem
,Content
, orProperty
in their name).
Potential future enhancement:
PowerShell's tab-completion logic is currently hard-wired to:
- default to escaped completion,
- except if the target parameter name (if known) happens to be
-LiteralPath
GitHub issue #14149 proposes:
- defaulting to literal completion.
- except if the target parameter (if known) explicitly signals support for wildcard patterns via the
SupportsWildcardsAttribute
When to use Start-Process
vs. Invoke-Item
:
Simply put,
Start-Process
is a superset ofInvoke-Item
; the former is typically used to launch GUI executables, whereas the latter is typically used to open documents with the application registered to handle them or directories in File Explorer (on Windows).While
Start-Process
can do everythingInvoke-Item
can do and more, a crucial difference which amounts to a pitfall is thatStart-Process
looks for a file or directory identified by name only in the directories listed in$env:PATH
first rather than only in the current directory; prefixing the name with.\
(or using a full path) avoids this ambiguity.
# Unambiguously targets .\file.txt, i.e. a file in the *current* dir.
# In other words: The same as:
# Invoke-Item .\file.txt
Invoke-Item file.txt
# AMBIGUOUS:
# !! *First* looks for a file.txt file in the directories
# !! listed in $env:PATH and opens the first one it finds.
# !! Only if none is found does it look in the current dir.
Start-Process file.txt
# OK - unambiguously looks in the current dir. only, thanks to ".\"
Start-Process .\file.txt
Note:
- Since
Start-Process
is typically used to launch executables (GUI executables; except for special situations, it is the wrong tool for launching console applications), looking in$env:PATH
(first) makes sense, but that the behavior also extends to documents (non-executables) is unexpected and problematic - see GitHub issue #9469.
On the plus side, Start-Process
(unlike Invoke-Item
) can open URLs in the default web browser; e.g.:
Start-Process http://example.org
In summary:
- It is fine to always use
Start-Process
in lieu ofInvoke-Item
, as long as you avoid ambiguity by prefixing target items in the current directory with.\
- fortunately, tab-completion for items in the current dir. automatically adds this prefix.