问题
I am using jq 1.6 on Windows 8.1 and facing same issue as reported here https://github.com/stedolan/jq/issues/1644
Command as simple as jq . *.json
is failing with following error:
Assertion failed!
Program: jq.exe File: src/main.c, Line 256 Expression: wargc == argc
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.
Does anyone have solution to this? What is the correct way to use jq
with all the files in the folder on windows?
回答1:
This is a curious problem.
As alredy answered by peak, cmd.exe
does not expand wildcards, leaving this work to the programs. And jq
does not handle wildcards (from the issues list, more later).
But this is not the full reason for this failure.
As the question points, source code fails in an assert: wargc == argc
. When reading the source code, in windows jq
tries to process the original command line with
wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &wargc);
trying to retrieve the equivalent to argv[]
and argc
but handling multibyte arguments.
As cmd
is not expanding the wildcard there will be three arguments (command line in question)
jq . *.json
^^ ^ ^....^
0 1 2
both in argv[]
and wargv[]
, so argc
and wargc
should match.
Then, why does it fail? Why argc
is different to wargc
?
Because GCC was used to compile the program.
And no, the problem is not GCC itself. The "problem" is that the argument handling in GCC runtime DOES expand the wildcard (Microsoft compiler runtime does not, but it doesn't matter as it will also not solve the problem).
That means that argc
and argv
(determined by GCC code with wildcard expansion) will contain information according to the number of files matching the wildcard while wargc
and wargv
(determined by MS code without wildcard expansion) will not.
A simple way to probe it is to have only one .json
file when trying the previous command. The assert will not fail but jq
will fail with jq: error: Could not open file *.json: Invalid argument
as it does not handle wildcards.
jq . test.json As seen in argv argc = 3
jq . *.json As seen in wargv wargc = 3
So, how to deal with it? Without modifying the jq
's source code your best option is to concatenate the list of files and pass it to jq
. References in peak's answer and in your comment should deal with the problem.
But remember that in cmd
and batch files your command lines are limited to 8191 characters. If it is not enough to deal with your problem you can try with something like (yes, a lot of lines, most of them comments and command usage)
@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 );
};
Save it as a cmd
file (ex. list2args.cmd
) and use it as suggested
dir /b *.json | list2args.cmd jq .
The difference is that doing the concatenation inside the script part and starting the process using the WScript.Shell.Exec
method we can use command lines up to 32KB (the windows limit for command lines).
回答2:
As explained at https://en.wikibooks.org/wiki/Windows_Batch_Scripting
"Unlike shells of some other operating systems, the cmd.exe shell does not perform wildcard expansion"
So assuming you can't simply process the files one at a time, you'll either have to create the list of files explicitly, or use a different shell.
For further details and suggestions, see https://superuser.com/questions/460598/is-there-any-way-to-get-the-windows-cmd-shell-to-expand-wildcard-paths
and if you’re using Windows 10:
https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/
来源:https://stackoverflow.com/questions/53387811/using-wildcard-for-files-with-jq-on-windows