我正在Windows 8.1上使用jq 1.6,并且遇到与此处报告的相同的问题 https://github.com/stedolan/jq/issues/1644
简单到jq . *.json
的命令失败,并显示以下错误:
断言失败!
程序:jq.exe 文件:src / main.c,第256行 表达式:wargc == argc
此应用程序已请求运行时 以不寻常的方式终止它。请联系应用程序的 支持团队以获取更多信息。
有人对此有解决方案吗?在Windows文件夹中的所有文件中使用jq
的正确方法是什么?
答案 0 :(得分:2)
这是一个奇怪的问题。
正如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应该可以解决问题。
但是请记住,在cmd
和批处理文件中,命令行限制为8191个字符。如果不足以解决您的问题,您可以尝试使用类似的方法(是的,很多行,其中大多数是注释和命令用法)
@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(命令行的窗口限制)的命令行。
答案 1 :(得分:1)
如https://en.wikibooks.org/wiki/Windows_Batch_Scripting
所述“与某些其他操作系统的外壳不同,cmd.exe外壳不执行通配符扩展”
因此,假设您不能一次简单地处理一个文件,则要么必须 显式创建文件列表,或使用其他Shell。
有关更多详细信息和建议,请参阅 https://superuser.com/questions/460598/is-there-any-way-to-get-the-windows-cmd-shell-to-expand-wildcard-paths
,如果您使用的是Windows 10:
https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/