我在Windows上的git bash中使用以下git命令:
git log --format="%C(cyan)%cd%Creset %s" --date=short -5
它显示提交日期(%cd
),后跟提交消息(%s
)。提交日期包含颜色标记:%C(cyan)
以启动彩色输出,%Creset
以停止彩色输出。
虽然它在git bash中运行良好,但它与cmd
的效果不佳:%cd%
由Windows shell扩展到当前工作目录(相当于bash中的$PWD
)。
因此,当该命令通过cmd
运行时,我会在第一列中看到当前工作目录而不是提交日期!
git bash:
2015-10-08 commit msg
2015-10-08 commit msg
2015-10-07 commit msg
2015-10-06 commit msg
2015-10-06 commit msg
CMD:
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
D:\git\someFolderCreset commit msg
实际上,我从不直接使用cmd
,我在编写nodejs(0.12)脚本时发现了这种行为
require('child_process').execSync('git log --format=...', {stdio: 'inherit'})
在Windows上使用cmd
由节点执行。)
一个简单的解决方法可能是引入一个空格来阻止找到%cd%
,即更改
git log --format="%C(cyan)%cd%Creset %s" --date=short -5
到
git log --format="%C(cyan)%cd %Creset%s" --date=short -5
然而,这引入了一个冗余空间(我在%s
之前删除了另一个空格,但它仍然是一个黑客,需要手动干预)。
有没有办法防止Windows shell扩展?
我有found有关使用%%
或^%
来逃避%
的信息,但它们不是解决方案:
# produces superfluous ^ characters
git log --format="%C(cyan)^%cd^%Creset %s" --date=short -5
^2015-10-08^ commit msg
^2015-10-08^ commit msg
^2015-10-07^ commit msg
^2015-10-06^ commit msg
^2015-10-06^ commit msg
# seems the expansion is done at command parse time
git log --format="%C(cyan)%%cd%%Creset %s" --date=short -5
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
%D:\git\someFolder commit msg
理想的解决方案应该是与bash和cmd兼容,而不是产生冗余字符,或者在javascript中使用转义函数来逃避Windows的通用UNIX-y命令以防止扩展(如果可以创建这样的转义函数) 。
答案 0 :(得分:4)
提供MC ND's helpful answer的替代方案:
如果您确实需要来获取 shell (这不太可能,因为您声明您希望命令同时使用Windows' cmd.exe
和 Bash),请考虑下面的解决方案;对于绕过问题的 无shell 备选方案,请参阅底部的解决方案。
通过建议在%
个实例周围放置双引号而不是 {{之间的潜在变量名称来改进原始方法的提示[/ 3}} 1}}个实例,并建议澄清重新%
。
execFileSync
字符。对于%
如MC ND中所述,您无法在Windows命令提示符处(在cmd.exe
批处理文件内)从技术上逃避%
,但在调用shell时这不起作用来自其他环境(如Node.js)的命令,通常不会跨平台工作。
但是,解决方法是在每个%%
实例周围放置双引号:
%
插入的双引号会阻止// Input shell command.
var shellCmd = 'git log --format="%C(cyan)%cd%Creset %s" --date=short -5'
// Place a double-quote on either end of each '%'
// This yields (not pretty, but it works):
// git log --format=""%"C(cyan)"%"cd"%"Creset "%"s" --date=short -5
var escapedShellCmd = shellCmd.replace(/%/g, '"%"')
// Should work on both Windows and Unix-like platforms:
console.log(require('child_process').execSync(escapedShellCmd).toString())
将cmd.exe
等标记识别为变量引用(%cd%
不会被扩展)。
这样可行,因为当目标程序处理时,额外的双引号最终会从字符串中删除:
Windows :"%"cd"%"
(可能是通过C运行时)然后负责从合并后的字符串中删除额外的双引号。
类Unix (类似POSIX的shell,如Bash):shell本身会在将双引号传递给目标程序之前将其删除。
git.exe
上执行可能不需要的扩展-prefixed tokens(这里不是问题);但是,为了保持与Windows兼容,必须使用双引号。 从技术上讲,将此技术应用于双引号字符串会将其分解为一系列双引号子字符串,其中散布着未引用的 $
实例。类似POSIX的shell仍然将其识别为单个字符串 - 子字符串是双引号并直接邻接%
个实例。 (如果将该技术应用于未加引号字符串,则逻辑相反:您在双引号%
实例中有效拼接。)子字符串周围的双引号,当子串连接在一起形成单个文字以传递给目标程序时,它们被认为是语法元素而不是字符串的一部分。
功能
注意:以下构建于%
,仅适用于调用外部可执行文件 (在OP& #39; s case:execFile[Sync]
) - 相比之下,对于调用 shell builtins (内部命令)或Windows 批处理文件,您无法避免{{1}因此git.exe
解释(在Windows上)。 [1]
如果您使用MC ND's answer 而不是exec[Sync]
,则 shell(Windows上为cmd.exe
)将不会涉及,因此您无需担心转义execSync
字符。或任何其他shell元字符,就此而言:
cmd.exe
请注意必须将单独作为数组的元素提供,而不使用嵌入式引号
。 [1]在Windows上,无法使用%
直接调用脚本文件(例如,Python脚本),但您可以将解释器可执行文件(例如,require('child_process').execFileSync('git',
[ 'log',
'--format=%C(cyan)%cd%Creset %s',
'--date=short',
'-5' ], {stdio: 'inherit'})
)作为要执行的文件,以及脚本文件作为参数。在类似Unix的平台上,你可以直接调用脚本,只要它们有execFileSync
并标记为可执行文件。
execFile[Sync]
可以用于调用Windows 批处理文件,但python
总是插入参数,与execFile[Sync]
一样。
答案 1 :(得分:3)
简而言之,你做不到或者至少没有一般的方法
注意我错了。 mklement0's answer为一般解决方案指明了方向。
当然,您可以使用^
,而不是逃避百分号(您无法在命令行级别转义百分号),而是将百分号与变量名称分开,因此它不是检测为要扩展的变量。也就是说,对于您的情况,使用
git log --format="%C(cyan)%cd^%Creset %s" --date=short -5
但正如您所指出的那样,插入符号不会使用插入符号并包含在输出字符串中。
因此,任何"转义" 字符都将包含在cmd
和bash
的输出中,但可以针对此特定字符进行求解(或类似)使用
process.env.cd = '%cd%'
require('child_process').execSync(
'git log --format="%C(cyan)%cd%Creset %s" --date=short -5'
, {stdio: 'inherit'}
)
基本上,代码所做的是为cd
环境变量分配一个伪值,将其更改为文字%cd%
,因此,当cmd
解析器执行变量扩展时,正确的值在命令行中结束。
但是,也许(我没有检查git
代码如何/更改cd
变量可能会干扰)。因此,对于这种情况,您可以使用
cd
变量的值
process.env['C(cyan)'] = '%C(cyan)%';
为什么呢?当cmd
解析器处理命令行时,它将匹配格式字符串与现有变量的开头,执行扩展并在同一进程中使用%cd%
变量中的起始百分号,它没有扩大。