bash 在传递给 unix 程序的 Windows 路径中转义反斜杠

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7962485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:08:49  来源:igfitidea点击:

Escaping backslash in windows paths passed to unix programs

bashcygwin

提问by Flethuseo

I am trying to escape backslashes in cygwin, but it seems almost impossible I have tried a lot of things, but none work right..

我试图逃避 cygwin 中的反斜杠,但我尝试了很多东西似乎几乎不可能,但没有一个工作正常..

  echo "C:\Users\Ted\Documents\Unix\Scripts" | xargs echo
  echo 'C:\Users\Ted\Documents\Unix\Scripts' | xargs echo

More specifically I need to get a command to receive input in bash without losing the backslash characters. every time I try to pass an argument, the backslashes always disappear, destroying my input. And I don't know how I can tell it to just leave the backslashes on the input alone.

更具体地说,我需要获得一个命令以在 bash 中接收输入而不会丢失反斜杠字符。每次我试图传递一个参数时,反斜杠总是消失,破坏我的输入。而且我不知道如何告诉它只在输入上留下反斜杠。

I have tried the following but neither seems work

我已经尝试了以下但似乎都没有工作

  alias cyg0='cygpath '$*'  '
  alias cyg1='cygpath "$*"  '
  alias cyg2='cygpath "'$*'"'

  alias cyg3='cygpath '$@'  '
  alias cyg4='cygpath "$@"  '
  alias cyg5='cygpath "'$@'"'


  Ted@Machine01 ~
  $ cyg0 C:\Users\Ted\Music\Enigma
  C:UsersTedMusicEnigma

  Ted@Machine01 ~
  $ cyg1 C:\Users\Ted\Music\Enigma
  cygpath: can't convert empty path

  Ted@Machine01 ~
  $ cyg2 C:\Users\Ted\Music\Enigma
  cygpath: can't convert empty path

  Ted@Machine01 ~
  $ cyg3 C:\Users\Ted\Music\Enigma
  C:UsersTedMusicEnigma

  Ted@Machine01 ~
  $ cyg4 C:\Users\Ted\Music\Enigma
  C:UsersTedMusicEnigma

  Ted@Machine01 ~
  $ cyg5 C:\Users\Ted\Music\Enigma
  cygpath: can't convert empty path

By the way, I want to be able to type C:\Users\Ted\Music\Enigma without quotes. One of those aliases works when using quotes.

顺便说一句,我希望能够输入 C:\Users\Ted\Music\Enigma 而不带引号。这些别名之一在​​使用引号时有效。

Ted

泰德

回答by Andrew Schulman

Please read the section titled QUOTING in bash(1) (man bash).

请阅读 bash(1) ( man bash) 中标题为 QUOTING 的部分。

In your first example,

在你的第一个例子中,

echo "C:\Users\Ted\Documents\Unix\Scripts" | xargs echo

the shell interprets (and then removes) backslashes within double quotes, so the first echocommand only sees the string C:UsersTedDocumentsUnixScripts.

shell 解释(然后删除)双引号内的反斜杠,因此第一个echo命令只能看到字符串C:UsersTedDocumentsUnixScripts.

In your second example,

在你的第二个例子中,

echo 'C:\Users\Ted\Documents\Unix\Scripts' | xargs echo

the single quotes correctly protect the backslashes, as you can see by running just the first echocommand, without the | xargs echo.

单引号正确保护反斜杠,正如您可以通过仅运行第一个echo命令看到的,没有| xargs echo.

In all of your remaining examples,

在你剩下的所有例子中,

cyg0 C:\Users\Ted\Music\Enigma
cyg1 C:\Users\Ted\Music\Enigma
...

since the argument (C:\Users\Ted\Music\Enigma) is unquoted, once again the shell interprets and removes the backslashes before the command (cyg0, cyg1, ...) ever sees them. And...

由于参数 ( C:\Users\Ted\Music\Enigma) 未加引号,shell 再次在命令 ( cyg0, cyg1, ...) 看到它们之前解释并删除反斜杠。和...

I want to be able to type C:\Users\Ted\Music\Enigma without quotes.

我希望能够在没有引号的情况下键入 C:\Users\Ted\Music\Enigma。

Sorry, it can't be done. If you don't put the backslashes in single quotes, the shell will interpret each one as a quoting character for the character that follows it, then remove the backslash.

对不起,这是做不到的。如果不将反斜杠放在单引号中,shell 会将每个反斜杠解释为后面字符的引用字符,然后删除反斜杠。

You have a few options:

您有几个选择:

  1. Use single quotes on the command line, to protect the backslashes:

    cyg4 'C:\Users\Ted\Music\Enigma'
    
  2. Quote each backslash character separately, by doubling it, e.g.

    cyg4 C:\Users\Ted\Music\Enigma
    
  3. Use forward slashes instead:

    cyg4 C:/Users/Ted/Music/Enigma
    
  1. 在命令行上使用单引号来保护反斜杠:

    cyg4 'C:\Users\Ted\Music\Enigma'
    
  2. 分别引用每个反斜杠字符,将其加倍,例如

    cyg4 C:\Users\Ted\Music\Enigma
    
  3. 改用正斜杠:

    cyg4 C:/Users/Ted/Music/Enigma
    

Option 3 could really be your best solution. Unfortunately the backslash character is just a very special character for all Unix shells, and this causes a lot of quoting hassles when dealing with DOS/Windows paths. But what's not widely known is that DOS/Windows is also perfectly happy to use the forward slash (/) as its path separator. Try it.

选项 3 可能真的是您最好的解决方案。不幸的是,反斜杠字符对于所有 Unix shell 来说只是一个非常特殊的字符,这在处理 DOS/Windows 路径时会导致很多引用麻烦。但鲜为人知的是,DOS/Windows 也非常乐意使用正斜杠 ( /) 作为其路径分隔符。尝试一下。

Note: Of your several cyg* functions, only cyg1 and cyg4 are correct. The others use incorrect quoting. cyg1 is only useful with one argument since it joins all of the arguments together into one quoted string, while cyg4 can accept and pass on multiple arguments to cygpath. However, since cyg4 only passes on its quoted arguments, it doesn't add any value; it's really no different from just e.g.

注意:在您的几个 cyg* 函数中,只有 cyg1 和 cyg4 是正确的。其他人使用不正确的引用。cyg1 只对一个参数有用,因为它将所有参数连接到一个带引号的字符串中,而 cyg4 可以接受多个参数并将其传递给 cygpath。但是,由于 cyg4 只传递其引用的参数,因此它不会添加任何值;真的和 eg 没什么不同

cygpath C:/Users/Ted/Music/Enigma

Good luck.

祝你好运。

回答by Vittorio Muth

I had a similar problem when reading a path from windows explorer pasted into command line:

从粘贴到命令行的 Windows 资源管理器中读取路径时,我遇到了类似的问题:

echo "Please enter path (copy n paste from Win-Explorer):"
read -r myWinPath;

The "read -r xyz" command (with arg. "-r") does not interprete single backslashes in the pasted path.

“read -r xyz”命令(带有参数“-r”)不会解释粘贴路径中的单个反斜杠。

myNewCygwinPath=`cygpath -a $myWinPath`;
echo $myNewCygwinPath;

Vittorio

维托里奥

回答by newby2000

Sometimes it is useful to give manuals of the used programs a try :-) . From man xargs:

有时尝试一下使用过的程序的手册是很有用的 :-) 。来自man xargs

OPTIONS
   -0, --null
          Input items are terminated by a null character instead  of  by
          whitespace,  and the quotes and backslash are not special (ev-
          ery character is taken literally).  Disables the end  of  file
          string, which is treated like any other argument.  Useful when
          input items might contain white space, quote marks,  or  back-
          slashes.   The GNU find -print0 option produces input suitable
          for this mode.

This option indeed preserves the whole line as is. Try:

此选项确实保留了整行。尝试:

echo 'C:\Users\Ted\Documents\Unix\Scripts' | xargs -0 echo

The "-0" does it for you!

“-0”为你做!

Note that for more than one arg you must zero-terminate the arguments, for example by find ... -print0or grep ... --null.

请注意,对于多个 arg,您必须将参数以零结尾,例如通过find ... -print0grep ... --null

回答by CrashNeb

I recognize this answer is quite late to the party... but I stumbled across this question while having the same trouble myself.

我知道这个答案对聚会来说已经很晚了……但是我自己也遇到了同样的麻烦时偶然发现了这个问题。

I was using 'xargs' from a Cygwin installation - AND - I was invoking it from a regular cmd.exeshell.

我正在使用 Cygwin 安装中的“xargs” - 而且 - 我是从常规cmd.exeshell调用它的。

For me, I simply used the trutility that is also in the Cygwin folder:

对我来说,我只是使用tr了 Cygwin 文件夹中的实用程序:

dir /b /s /a *.txt | tr "\\" "/" | xargs ...

dir /b /s /a *.txt | tr "\\" "/" | xargs ...

This completely solved my "slash problem".

这完全解决了我的“斜线问题”。

回答by Urthona

I had the same problem, when converting filenames like c:\dirname to unix using cygpath I was getting c:dirname, and even weirder stuff.

我遇到了同样的问题,当使用 cygpath 将 c:\dirname 之类的文件名转换为 unix 时,我得到了 c:dirname,甚至更奇怪的东西。

Turns out, though, that my problem was the filenames I was using were input by users which I was retrieving with the "read" command. The read, not cygpath, was causing my problems by throwing out the backslash. "read -r" fixed the problem.

但事实证明,我的问题是我使用的文件名是由我使用“读取”命令检索的用户输入的。通过抛出反斜杠,读取而不是 cygpath 导致了我的问题。“read -r”解决了这个问题。

回答by lkisac

Try:

尝试:

echo "C:\Users\Ted\Documents\Unix\Scripts" | xargs -0 echo
echo 'C:\Users\Ted\Documents\Unix\Scripts' | xargs -0 echo

xargs -0option explanation (from gnu.org):

xargs -0选项说明(来自gnu.org):

"Input file names are terminated by a null character instead of by whitespace, and any quotes and backslash characters are not considered special (every character is taken literally). Disables the end of file string, which is treated like any other argument."

“输入文件名由空字符而不是空格终止,任何引号和反斜杠字符都不会被视为特殊字符(每个字符都按字面意思)。禁用文件字符串的结尾,它被视为任何其他参数。”

OR

或者

You can also achieve this with sed:

您也可以使用sed实现此目的:

echo "C:\Users\Ted\Documents\Unix\Scripts" | sed 's/\/\\/g' | xargs echo
echo 'C:\Users\Ted\Documents\Unix\Scripts' | sed 's/\/\\/g' | xargs echo

This will replace allsingle \with double \\before it is passed to xargs where the double \\will then be stripped back to single \, instead of the original case of single to none.

这将在传递给 xargs 之前用 double替换所有single \,然后\\double\\将被剥离回 single \,而不是原来的 single 到 none 的情况。

sedis a useful stream editor tool that can be used for simple text replacement. Here's a tutorialwith some good examples.

sed是一个有用的流编辑器工具,可用于简单的文本替换。这是一个带有一些很好示例的教程

Syntax for substitution is as follows:

替换的语法如下:

s/string_to_replace/replace_with/g

s/string_to_replace/replace_with/g

  • The gmodifier is used to replace alloccurrences. Without it, only the first match would be replaced.
  • The extra backslashes in sed 's/\\/\\\\/g'are used to escapeeach \character's special meaning. So, \\would be the literal character \, and \\\\would be \\.
  • g改性剂是用来取代所有出现。没有它,只有第一场比赛会被替换。
  • 中的额外反斜杠sed 's/\\/\\\\/g'用于转义每个\字符的特殊含义。因此,\\将是文字字符\,并且\\\\将是\\

For no quotes, you would have to use \\instead of \, as the marked answer suggests.

对于没有引号,您必须使用\\而不是\,正如标记的答案所暗示的那样。

 echo C:\Users\Ted\Documents\Unix\Scripts | xargs echo