为什么在Linux中Process.Startshell命令会失败,并出现“未终止的带引号的字符串”?

vxf3dgd4  于 2023-05-07  发布在  Shell
关注(0)|答案(1)|浏览(139)

问题
我试图从C#代码中运行7z来提取一些文件。该命令在Windows下工作,或者如果我只是从shell直接运行它,而不是从代码运行它。也许并不完全一样,我没有意识到。
所以我这样做:

//Unpack dump with 7z
StringBuilder argument = new($"\"{Config.zipPath}\" x \"{dumpPath}\" -so | \"{Config.zipPath}\" x -y -si -ttar");
foreach (string file in new[] { "vn", "vn_titles" /* and other strings */ }) {
    argument.Append($" db/{file} db/{file}.header");
}
Process.Start(Config.shell, string.Format(Config.arguments, argument)).WaitForExit();

配置文件是加载到静态Config类中的键=值对的列表。它适用于Windows:

shell=cmd.exe
zipPath=C:/Program Files/7-Zip-Zstandard/7z.exe
arguments=/C "{0}"

但不适用于Linux:

shell=ash
zipPath=7z
arguments=-c '{0}'

ash命令失败,出现错误:
x: line 0: syntax error: unterminated quoted string

我试过/检查过的一些东西

  • C#代码运行没有错误,至少直到它需要访问不存在的解压缩文件。
  • Config.shellash
  • string.Format(Config.arguments, argument)-c '"7z" x "dump.tar.zst" -so | "7z" x -y -si -ttar db/vn db/vn.header db/vn_titles db/vn_titles.header db/releases db/releases.header db/releases_titles db/releases_titles.header db/releases_vn db/releases_vn.header db/vn_length_votes db/vn_length_votes.header db/tags db/tags.header db/tags_parents db/tags_parents.header db/tags_vn db/tags_vn.header'
  • 基于前面的两点,我假设执行的命令是这两个命令的串联,即ash -c '"7z" x "dump.tar.zst" -so | "7z" x ... ',并且手动运行该命令可以按预期工作。所以我真的很难弄清楚问题出在哪里。

非理想解

knittl提供的答案应该是正确的,据我所知。无论是Windows还是Linux,shell都应该使用两个参数来调用--c(或/C,用于Windows的cmd),然后是我想要运行的命令,正确的是argument字符串。这通常是最简单的方法。但它在Windows下不起作用。
cmd似乎根本不支持\C参数中的路径名中的空格。不将它们括在引号中将无法将它们识别为单个字符串,而将它们括在引号中将使路径无效,因为引号不是路径的一部分。
powershell没有这个问题,但是-c的参数限制为256个字符,这也使得我的命令无法使用。
因此,解决方案是通过Environment.OSVersion.Platform检测我在哪个操作系统上,并将参数作为Unix的字符串数组传递,或者使用Win32 NT的cmd /C命令的特殊功能,如果命令的第一个字符是",它实际上不会解析整个命令,但是如果它也是一个"的话,只去掉它和最后一个字符,这样我就不用在命令中转义这些字符了,这是我最初的版本能够工作的唯一原因。

yr9zkbsy

yr9zkbsy1#

-c '...'必须是两个参数(-c和引号内的任何参数)。我不确定Process.Start(string, string)重载是如何将第二个参数分割成命令行参数的,但从你的问题来看,它似乎没有像一个(或你的shell)所期望的那样分割它们:)
你想调用重载Start(string, IEnumerable<string>)

Process.Start(Config.shell, new[]{ "-c",  argument })

相关问题