Terminal should always wrap drag-dropped paths in double quotes #11228

Open
opened 2026-01-31 02:42:01 +00:00 by claunia · 23 comments
Owner

Originally created by @Qu-Dasheng on GitHub (Oct 30, 2020).

Environment

Microsoft Windows [版本 10.0.18363.1139]
Windows Terminal [ powershell]
版本: 1.3.2651.0
python 3.7

Steps to reproduce

1.write the followings code
xx.py
import sys
with open(sys.argv[1]) as f:
pass
2.create a txt as "xxx(1).txt", the name must include"()"
3:open windows terminal powershell, cd to the xx.py directory
input “python xx.py”
drop the txt into terminal
run
4.if the filename contain "(xx)" can not resolve the path.

Expected behavior

it worked in cmd
open the file success

Actual behavior

FileNotFoundError: [Errno 2] No such file or directory: 'C:\Users\xx\Desktop\\input'

Originally created by @Qu-Dasheng on GitHub (Oct 30, 2020). <!-- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING: 1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement. 2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement. 3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number). 4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement. 5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement. All good? Then proceed! --> <!-- This bug tracker is monitored by Windows Terminal development team and other technical folks. **Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**. Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue. If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link. Please use this form and describe your issue, concisely but precisely, with as much detail as possible. --> # Environment Microsoft Windows [版本 10.0.18363.1139] Windows Terminal [ powershell] 版本: 1.3.2651.0 python 3.7 # Steps to reproduce 1.write the followings code xx.py import sys with open(sys.argv[1]) as f: pass 2.create a txt as "xxx(1).txt", the name must include"()" 3:open windows terminal powershell, cd to the xx.py directory input “python xx.py” drop the txt into terminal run 4.if the filename contain "(xx)" can not resolve the path. # Expected behavior it worked in cmd open the file success <!-- A description of what you're expecting, possibly containing screenshots or reference material. --> # Actual behavior FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\xx\\Desktop\\\\input' <!-- What's actually happening? -->
Author
Owner

@Qu-Dasheng commented on GitHub (Oct 30, 2020):

it alse crashed a few mins later, if drop the file into powershell,

@Qu-Dasheng commented on GitHub (Oct 30, 2020): it alse crashed a few mins later, if drop the file into powershell,
Author
Owner

@skyline75489 commented on GitHub (Oct 30, 2020):

Based on what I understand, this isn't a terminal issue. For python to recognize the path, you'll need manually escape the path using something like C:\\Users\\xx\\Desktop\\xxx.txt.

@skyline75489 commented on GitHub (Oct 30, 2020): Based on what I understand, this isn't a terminal issue. For python to recognize the path, you'll need manually escape the path using something like `C:\\Users\\xx\\Desktop\\xxx.txt`.
Author
Owner

@skyline75489 commented on GitHub (Oct 30, 2020):

The crash may be related to #7804 . But #7804 is an instantaneous crash instead of "a few mins later" one. So I'm not very positive about this.

@skyline75489 commented on GitHub (Oct 30, 2020): The crash may be related to #7804 . But #7804 is an instantaneous crash instead of "a few mins later" one. So I'm not very positive about this.
Author
Owner

@zadjii-msft commented on GitHub (Oct 30, 2020):

Does this work in powershell outside of the Terminal? (e.g. in powershell.exe launched directly from the run dialog or Start Menu?)

@zadjii-msft commented on GitHub (Oct 30, 2020): Does this work in powershell _outside_ of the Terminal? (e.g. in `powershell.exe` launched directly from the run dialog or Start Menu?)
Author
Owner

@zadjii-msft commented on GitHub (Oct 30, 2020):

@alannt777 Okay that doesn't really look like the issue at hand though, that just looks like explorer glitched out and thought you double clicked the file tbh.

@zadjii-msft commented on GitHub (Oct 30, 2020): @alannt777 Okay that doesn't really look like the issue at hand though, that just looks like explorer glitched out and thought you double clicked the file tbh.
Author
Owner

@ghost commented on GitHub (Oct 30, 2020):

@zadjii-msft Looks like it came before I pressed enter and that enter never made into powershell. I will update the GIF anyway.

@ghost commented on GitHub (Oct 30, 2020): @zadjii-msft Looks like it came before I pressed enter and that enter never made into powershell. I will update the GIF anyway.
Author
Owner

@ghost commented on GitHub (Oct 30, 2020):

@zadjii-msft I have updated the GIF. Looks like a PowerShell issue (I did not try this in cmd but the author said that it works)

@ghost commented on GitHub (Oct 30, 2020): @zadjii-msft I have updated the GIF. Looks like a PowerShell issue (I did not try this in cmd but the author said that it works)
Author
Owner

@ghost commented on GitHub (Oct 30, 2020):

Repro in (PowerShell) Terminal:

repro in terminal

Same thing happens in conhost.exe with PowerShell:

repro in conhost

@ghost commented on GitHub (Oct 30, 2020): Repro in (PowerShell) Terminal: ![repro in terminal](https://user-images.githubusercontent.com/67918878/97714900-be746a00-1ae7-11eb-9d4f-e098662d3c6f.gif) Same thing happens in conhost.exe with PowerShell: ![repro in conhost](https://user-images.githubusercontent.com/67918878/97720440-4a899000-1aee-11eb-8d62-7a5337c9803f.gif)
Author
Owner

@ghost commented on GitHub (Oct 31, 2020):

(1).txt part of the path is getting ignored by either python/powershell

Most likely it is powershell if it works fine in cmd.exe

@ghost commented on GitHub (Oct 31, 2020): `(1).txt` part of the path is getting ignored by either python/powershell Most likely it is powershell if it works fine in cmd.exe
Author
Owner

@Qu-Dasheng commented on GitHub (Oct 31, 2020):

Does this work in powershell outside of the Terminal? (e.g. in powershell.exe launched directly from the run dialog or Start Menu?)

It not wor

Based on what I understand, this isn't a terminal issue. For python to recognize the path, you'll need manually escape the path using something like C:\\Users\\xx\\Desktop\\xxx.txt

With open(r”%s” %sys.argv[1]) as f:pass

it not worked as well,and the escape only happened by “/“ or “\” ,the file name like xx(xx).txt , the power shell resolved the name as “xx”,del the tail “(xx).txt” .if drop the file into terminal,and add “ at the path beginning and ends, it will be work.

@Qu-Dasheng commented on GitHub (Oct 31, 2020): > Does this work in powershell _outside_ of the Terminal? (e.g. in `powershell.exe` launched directly from the run dialog or Start Menu?) It not wor > Based on what I understand, this isn't a terminal issue. For python to recognize the path, you'll need manually escape the path using something like `C:\\Users\\xx\\Desktop\\xxx.txt` With open(r”%s” %sys.argv[1]) as f:pass it not worked as well,and the escape only happened by “/“ or “\” ,the file name like xx(xx).txt , the power shell resolved the name as “xx”,del the tail “(xx).txt” .if drop the file into terminal,and add “ at the path beginning and ends, it will be work.
Author
Owner

@eryksun commented on GitHub (Oct 31, 2020):

Python relies on the C runtime to parse command line arguments. The CRT has no special handling of brackets -- only quote and backslash, so Python is not to blame here. This issue relates to how the console/terminal drop handler adds the filename to the input buffer, i.e. quoted or unquoted, and the shell's handling of special characters such as brackets in the given context.

Drag-and-drop of filenames is simple in POSIX because the filename can be dropped literally in single quotes. In contrast, Windows has a mix of shells -- including CMD, PowerShell, and bash -- which have different quoting rules. The console/terminal drop handler could quote every dropped file in double quotes, instead of just quoting files that have one or more spaces in them. That handles some but not all cases in CMD and PowerShell. It won't handle, for example, dropping a file named "test $home.txt" in PowerShell or "test %userprofile%.txt" in CMD. Shell variables or environment variables will still be evaluated in a string enclosed in double quotes. The user has to handle such cases manually.

@eryksun commented on GitHub (Oct 31, 2020): Python relies on the C runtime to [parse command line arguments](https://docs.microsoft.com/en-us/cpp/cpp/main-function-command-line-args?view=msvc-160#parsing-c-command-line-arguments). The CRT has no special handling of brackets -- only quote and backslash, so Python is not to blame here. This issue relates to how the console/terminal drop handler adds the filename to the input buffer, i.e. quoted or unquoted, and the shell's handling of special characters such as brackets in the given context. Drag-and-drop of filenames is simple in POSIX because the filename can be dropped literally in single quotes. In contrast, Windows has a mix of shells -- including CMD, PowerShell, and bash -- which have different quoting rules. The console/terminal drop handler could quote every dropped file in double quotes, instead of just quoting files that have one or more spaces in them. That handles some but not all cases in CMD and PowerShell. It won't handle, for example, dropping a file named `"test $home.txt"` in PowerShell or `"test %userprofile%.txt"` in CMD. Shell variables or environment variables will still be evaluated in a string enclosed in double quotes. The user has to handle such cases manually.
Author
Owner

@ghost commented on GitHub (Oct 31, 2020):

Quotes around the path would fix this problem:

Adding quotes would fix this problem

Possible "fix" for this is:

When a file is dragged into the Terminal, enclose the path in quotes

@ghost commented on GitHub (Oct 31, 2020): Quotes around the path would fix this problem: ![Adding quotes would fix this problem](https://user-images.githubusercontent.com/67918878/97772271-8e6eaa80-1b6b-11eb-9ec4-568ca78cd0fe.png) Possible *"fix"* for this is: When a file is dragged into the Terminal, enclose the path in quotes
Author
Owner

@ghost commented on GitHub (Oct 31, 2020):

With open(r”%s” %sys.argv[1]) as f:pass

There is no need to try to escape backslashes. Python does this for you:

image

@ghost commented on GitHub (Oct 31, 2020): > With open(r”%s” %sys.argv[1]) as f:pass There is no need to try to escape backslashes. Python does this for you: ![image](https://user-images.githubusercontent.com/67918878/97772387-882cfe00-1b6c-11eb-8627-d101e8e3b61d.png)
Author
Owner

@eryksun commented on GitHub (Oct 31, 2020):

When a file is dragged into the Terminal, enclose the path in quotes

This is already implemented if the filename contains spaces. I don't think it would be a problem to always do it.

Enclosing a string in double quotes escapes special characters in PowerShell (see about quoting rules), except for "$" variable substitution. Single-quote strings escape variable substitution as well. CMD only supports escaping via double-quote strings, which evaluate "%" variable substitutions. Either type allows passing (1) literally.

MSVC argv and WinAPI CommandLineToArgvW only support double-quote strings. PowerShell and WSL accommodate this by translating single-quote strings to double-quote strings in a command line, e.g. py.exe hello.py 'test(1).txt' gets passed to WinAPI CreateProcessW as py.exe hello.py "test(1).txt".

There is no need to try to escape backslashes. Python does this for you:

The arrow is pointing at the repr (string-literal representation) of the in-memory string "G:\Test\test". This isn't related to escaping of the command line. Python just uses the argv array that's parsed by MSVC.

@eryksun commented on GitHub (Oct 31, 2020): > When a file is dragged into the Terminal, enclose the path in quotes This is already implemented if the filename contains spaces. I don't think it would be a problem to always do it. Enclosing a string in double quotes escapes special characters in PowerShell (see [about quoting rules](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7)), except for "$" variable substitution. Single-quote strings escape variable substitution as well. CMD only supports escaping via double-quote strings, which evaluate "%" variable substitutions. Either type allows passing `(1)` literally. MSVC `argv` and WinAPI `CommandLineToArgvW` only support double-quote strings. PowerShell and WSL accommodate this by translating single-quote strings to double-quote strings in a command line, e.g. `py.exe hello.py 'test(1).txt'` gets passed to WinAPI `CreateProcessW` as `py.exe hello.py "test(1).txt"`. > There is no need to try to escape backslashes. Python does this for you: The arrow is pointing at the repr (string-literal representation) of the in-memory string "G:\Test\test". This isn't related to escaping of the command line. Python just uses the `argv` array that's parsed by MSVC.
Author
Owner

@Qu-Dasheng commented on GitHub (Oct 31, 2020):

Nb专业讲究

发自我的iPhone

在 2020年10月31日,下午4:44,Eryk Sun notifications@github.com 写道:



When a file is dragged into the Terminal, enclose the path in quotes

This is already implemented if the file contains spaces. I don't think it would be a problem to always do it.

Enclosing a string in double quotes escapes special characters in PowerShell (see about quoting ruleshttps://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7), except for "$" variable substitution. Single-quote strings escape variable substitution as well. CMD only supports escaping via double-quote strings, which evaluate "%" variable substitutions. Either type allows passing (1) literally.

MSVC argv and WinAPI CommandLineToArgvW only support double-quote strings. PowerShell and WSL accommodate this by translating single-quote strings to double-quote strings in a command line, e.g. py.exe hello.py 'test(1).txt' gets passed to WinAPI CreateProcessW as py.exe hello.py "test(1).txt".

There is no need to try to escape backslashes. Python does this for you:

The arrow is pointing at the repr (string-literal representation) of the in-memory string "G:\Test\test". This isn't related to escaping of the command line. Python just uses the argv array that's parsed by MSVC.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHubhttps://github.com/microsoft/terminal/issues/8109#issuecomment-719904515, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMD77YDGB2ASBHTPQKZ3NCDSNPE6VANCNFSM4TEVZZNQ.

@Qu-Dasheng commented on GitHub (Oct 31, 2020): Nb专业讲究 发自我的iPhone 在 2020年10月31日,下午4:44,Eryk Sun <notifications@github.com> 写道:  When a file is dragged into the Terminal, enclose the path in quotes This is already implemented if the file contains spaces. I don't think it would be a problem to always do it. Enclosing a string in double quotes escapes special characters in PowerShell (see about quoting rules<https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7>), except for "$" variable substitution. Single-quote strings escape variable substitution as well. CMD only supports escaping via double-quote strings, which evaluate "%" variable substitutions. Either type allows passing (1) literally. MSVC argv and WinAPI CommandLineToArgvW only support double-quote strings. PowerShell and WSL accommodate this by translating single-quote strings to double-quote strings in a command line, e.g. py.exe hello.py 'test(1).txt' gets passed to WinAPI CreateProcessW as py.exe hello.py "test(1).txt". There is no need to try to escape backslashes. Python does this for you: The arrow is pointing at the repr (string-literal representation) of the in-memory string "G:\Test\test". This isn't related to escaping of the command line. Python just uses the argv array that's parsed by MSVC. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub<https://github.com/microsoft/terminal/issues/8109#issuecomment-719904515>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AMD77YDGB2ASBHTPQKZ3NCDSNPE6VANCNFSM4TEVZZNQ>.
Author
Owner

@ghost commented on GitHub (Oct 31, 2020):

The arrow is pointing at the repr (string-literal representation) of the in-memory string "G:\Test\test". This isn't related to escaping of the command line. Python just uses the argv array that's parsed by MSVC.

Anyway, you don't have to escape it manually, right?

Enclosing a string in double quotes escapes special characters in PowerShell (see about quoting rules), except for "$" variable substitution. Single-quote strings escape variable substitution as well. CMD only supports escaping via double-quote strings, which evaluate "%" variable substitutions. Either type allows passing (1) literally.

We could replace with ` and replace % with what I believe is %%

@ghost commented on GitHub (Oct 31, 2020): > The arrow is pointing at the repr (string-literal representation) of the in-memory string "G:\Test\test". This isn't related to escaping of the command line. Python just uses the argv array that's parsed by MSVC. Anyway, you don't have to escape it manually, right? > Enclosing a string in double quotes escapes special characters in PowerShell (see [about quoting rules](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7)), except for "$" variable substitution. Single-quote strings escape variable substitution as well. CMD only supports escaping via double-quote strings, which evaluate "%" variable substitutions. Either type allows passing (1) literally. We could replace $ with `$ and replace % with *what I believe is %%*
Author
Owner

@eryksun commented on GitHub (Oct 31, 2020):

We could replace with ` and replace % with what I believe is %%

I think heading down the path of special-casing certain client processes would be confusing to the end user regarding which shells and applications are special cased. Also, %% is for batch scripts. AFAIK, CMD has no intended way to escape % at the interactive prompt. It executes an initial parse to substitute for % variables, which you can disrupt with CMD's ^ escape character, such as using %^SPAM% to 'escape' %SPAM%. This doesn't work if the variable name itself contains ^, such as set "^SPAM=EGGS" for a variable named ^SPAM.

@eryksun commented on GitHub (Oct 31, 2020): > We could replace $ with `$ and replace % with _what I believe is %%_ I think heading down the path of special-casing certain client processes would be confusing to the end user regarding which shells and applications are special cased. Also, `%%` is for batch scripts. AFAIK, CMD has no intended way to escape `%` at the interactive prompt. It executes an initial parse to substitute for `%` variables, which you can disrupt with CMD's `^` escape character, such as using `%^SPAM%` to 'escape' `%SPAM%`. This doesn't work if the variable name itself contains `^`, such as `set "^SPAM=EGGS"` for a variable named `^SPAM`.
Author
Owner

@ghost commented on GitHub (Oct 31, 2020):

This idea itself seems to be not very applicable and be confusing for the end users

@ghost commented on GitHub (Oct 31, 2020): This idea itself seems to be not very applicable and be confusing for the end users
Author
Owner

@zadjii-msft commented on GitHub (Nov 2, 2020):

Alright so after a very convoluted discussion, TL;DR:

  • This appears broken, because the filename isn't enclosed in double-quotes, and powershell treats the (1) in the file name as special characters.
  • This could be fixed by always wrapping drag-dropped paths in double quotes always. This would be safe for other shells as well as powershell.
  • This could also be worked-around by just manually wrapping the path in double quotes.

I'll make this issue track "always wrap drag-dropped paths in double quotes", and toss it on the backlog. Thanks all!

@zadjii-msft commented on GitHub (Nov 2, 2020): Alright so after a very convoluted discussion, **TL;DR**: * This appears broken, because the filename isn't enclosed in double-quotes, and powershell treats the `(1)` in the file name as special characters. * This could be fixed by always wrapping drag-dropped paths in double quotes _always_. This would be safe for other shells as well as powershell. * This could also be worked-around by just manually wrapping the path in double quotes. I'll make this issue track "always wrap drag-dropped paths in double quotes", and toss it on the backlog. Thanks all!
Author
Owner

@SnirBroshi commented on GitHub (Nov 5, 2020):

Can we have some configurable list of characters which must be quoted, for people who prefer it to not always quote?

We could keep this list of characters for common shells, but have it configurable for each profile for any other shells/

@SnirBroshi commented on GitHub (Nov 5, 2020): Can we have some configurable list of characters which must be quoted, for people who prefer it to not always quote? We could keep this list of characters for common shells, but have it configurable for each profile for any other shells/
Author
Owner

@oldium commented on GitHub (Dec 7, 2020):

I would not expect that the file name is dropped into any shell, it could be text editor, so it would make sense to make this feature completely optional, also the style of quotes (single, double).

@oldium commented on GitHub (Dec 7, 2020): I would not expect that the file name is dropped into any shell, it could be text editor, so it would make sense to make this feature completely optional, also the style of quotes (single, double).
Author
Owner

@Binly42 commented on GitHub (Aug 27, 2022):

Just FYI.

git-bash would auto wrap with single quotes if there is something like '(1)' or whitespace witnin the name of the drag-ed file.

That may also be a considerable design.

@Binly42 commented on GitHub (Aug 27, 2022): Just FYI. git-bash would auto wrap with single quotes if there is something like '`(1)`' or `whitespace` witnin the name of the drag-ed file. That may also be a considerable design.
Author
Owner

@zadjii-msft commented on GitHub (Jul 12, 2023):

xref #15646 - for WSL's, we'll want single quotes always.

@zadjii-msft commented on GitHub (Jul 12, 2023): xref #15646 - for WSL's, we'll want _single_ quotes always.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#11228