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 -
-FilePathparameter of theStart-Processcmdlet (startis built-in alias for it).Since
-FilePathonly 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
-Pathis inInvoke-Item'sdefault parameter set and is the first positional parameter, the tab-completed value would have worked as-is had you usedInvoke-Itemrather 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
-LiteralPathparameter and then does not perform escaping:# OK with tab-completion: due to explicitly targeting -LiteralPath, # no escaping is performed. Invoke-Item -LiteralPath .\[test].txtThe above applies to all provider cmdlets, such as
Get-ChildItemandGet-Content(roughly speaking, they comprise the cmdlets that have the wordItem,Content, orPropertyin 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-Processis 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-Processcan do everythingInvoke-Itemcan do and more, a crucial difference which amounts to a pitfall is thatStart-Processlooks for a file or directory identified by name only in the directories listed in$env:PATHfirst 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-Processis 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-Processin 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.
