Это любопытная проблема.
Поскольку alredy отвечает пиковым , 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
при попытке выполнить предыдущую команду.Assert не потерпит неудачу, но 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
. Ссылки в ответе пика и в вашем комментарии должны касаться проблемы.
Но помните, что в 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
) и использовать его как предложеноограничение окон для командной строки).