这是一个奇怪的问题。
正如answered by peak 一样,cmd.exe 不会扩展通配符,将这项工作留给程序。并且jq 不处理通配符(来自问题列表,稍后会详细介绍)。
但这并不是这次失败的全部原因。
正如问题所指出的,源代码在断言中失败:wargc == argc。阅读源码时,windows中jq尝试用
处理原命令行
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &wargc);
尝试检索与 argv[] 和 argc 等效的值,但处理多字节参数。
由于cmd 没有扩展通配符,所以会有三个参数(有问题的命令行)
jq . *.json
^^ ^ ^....^
0 1 2
在argv[] 和wargv[] 中,所以argc 和wargc 应该匹配。
那么,为什么会失败?为什么argc 与wargc 不同?
因为编译程序使用了GCC。
不,问题不在于 GCC 本身。 “问题”是 GCC 运行时中的参数处理确实扩展了通配符(Microsoft 编译器运行时没有,但没关系,因为它也不能解决问题)。
这意味着argc和argv(由带有通配符扩展的GCC代码确定)将包含根据匹配通配符的文件数量的信息,而wargc和wargv(由没有通配符扩展的MS代码确定) ) 不会。
一种简单的探测方法是在尝试上一个命令时只有一个.json 文件。断言不会失败,但jq 将失败并显示jq: error: Could not open file *.json: Invalid argument,因为它不处理通配符。
jq . test.json As seen in argv argc = 3
jq . *.json As seen in wargv wargc = 3
那么,如何处理呢?在不修改jq 的源代码的情况下,最好的选择是连接文件列表并将其传递给jq。 References 在 peak 的回答和您的评论中应该可以解决这个问题。
但请记住,在cmd 和批处理文件中,您的命令行限制为 8191 个字符。如果这不足以解决您的问题,您可以尝试使用类似的东西(是的,很多行,其中大部分是 cmets 和命令用法)
@if (@this==@isBatch) @then /* ------------------------------------- batch code
@echo off
setlocal enableextensions disabledelayedexpansion
rem This is an hybrid batch/javascript file. The batch part will retrieve
rem the required information and start the cscript engine to execute the
rem javascript part of this file.
rem Retrieve a safe reference to current batch file
call :getCurrentFile thisFile fileName
rem Arguments to current batch file are the command line to execute later
rem Using an environment variable to avoid losing quotes when using the
rem internal Wscript argumeng handling routines
set [commandLine]=%*
if not defined [commandLine] (
echo(
echo usage: command1 ^| "%fileName%" command2
echo(
echo where:
echo command1 is a command generating a set of lines that will be
echo concatenated to pass as arguments to command2
echo(
echo command2 is the command to execute with all the lines from
echo command1 as command line arguments
echo(
echo examples:
echo(
echo dir /b ^| "%fileName%" cmd /c echo
echo dir /b *.json ^| "%fileName%" jq .
echo(
goto :eof
)
rem Execute the javascript part of this script
"%windir%\system32\cscript.exe" //nologo //e:JScript "%thisFile%"
goto :eof
:getCurrentFile fullPath fileName
set "%~1=%~f0"
set "%~2=%~nx0"
goto :eof
------------------------------------------------------------- end of batch code
*/@end //------------------------------------------------------ javascript code
/*
This script will read all lines from standard input and execute the
command stored by the batch code above into the [commandLine] environment
variable, passing as command lien arguments the concatenation of all lines
present in the standard input.
*/
var shell = WScript.CreateObject('WScript.Shell')
, commandLine = shell.Environment("PROCESS").Item('[commandLine]')
, stdIn = WScript.StdIn
, stdOut = WScript.StdOut
, stdErr = WScript.StdErr
, line = ''
, buffer = []
;
// read the list of arguments from standard input
while ( !stdIn.AtEndOfStream ){
if (
line = stdIn.ReadLine().replace(/"/g, '')
) buffer.push( ' "' + line + '"' );
};
// concatenate all arguments
buffer = buffer.join('');
// if we don't have a command line, output what we have contatenated
// but if we have a command line, execute it, get its output and show it
// as it is possible that we are piping it to another process.
if ( commandLine ){
try {
stdOut.WriteLine(
shell.Exec( commandLine + buffer ).StdOut.ReadAll()
);
} catch ( e ){
stdErr.WriteLine( 'ERROR: Command line exec failed when running:' );
stdErr.WriteLine( '---------------------------------------------' );
stdErr.WriteLine( commandLine + buffer );
stdErr.WriteLine( '---------------------------------------------' );
};
} else {
stdOut.WriteLine( buffer );
};
将其保存为cmd 文件(例如list2args.cmd)并按照建议使用
dir /b *.json | list2args.cmd jq .
不同之处在于,在脚本部分进行连接并使用WScript.Shell.Exec 方法启动进程,我们可以使用最大 32KB 的命令行(命令行的窗口限制)。