Использование подстановочного знака для файлов с jq в Windows - PullRequest
0 голосов
/ 20 ноября 2018

Я использую jq 1.6 в Windows 8.1 и сталкиваюсь с той же проблемой, что и здесь. https://github.com/stedolan/jq/issues/1644

Команда, столь же простая, как jq . *.json, не выполняется со следующей ошибкой:

Утверждениеошибка!

Программа: jq.exe Файл: src / main.c, строка 256 Выражение: wargc == argc

Это приложение запросило среду выполнения, чтобы завершить ее необычным способом.Пожалуйста, обратитесь в службу поддержки приложения для получения дополнительной информации.

У кого-нибудь есть решение этой проблемы?Как правильно использовать jq со всеми файлами в папке на Windows?

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Это любопытная проблема.

Поскольку 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) и использовать его как предложеноограничение окон для командной строки).

0 голосов
/ 20 ноября 2018

Как объяснено на https://en.wikibooks.org/wiki/Windows_Batch_Scripting

"В отличие от оболочек некоторых других операционных систем, оболочка cmd.exe не выполняет расширение по шаблону"

Итак, если вы не можете просто обрабатывать файлы по одному, вам придется либо создайте список файлов явно или используйте другую оболочку.

Для получения дополнительной информации и предложений см. 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/

...