xargs命令长度限制

时间:2016-03-25 17:25:42

标签: bash xargs jsonlint

我正在使用jsonlint来抓取目录中的一堆文件(递归)。我写了以下命令:

find ./config/pages -name '*.json' -print0 | xargs -0I % sh -c 'echo Linting: %; jsonlint -V ./config/schema.json -q %;'

它适用于大多数文件,但有些文件我收到以下错误:

Linting: ./LONG_FILE_NAME.json
fs.js:500
 return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
                ^
  Error: ENOENT, no such file or directory '%'

长文件名似乎失败了。有没有办法来解决这个问题?感谢。

编辑1: 发现了问题。

  

-I replstr

     

为每个输入行执行实用程序,替换一个或多个实例   replstr的最多替换(如果没有指定-R标志则为5)   具有整个输入行的实用程序的参数。所结果的   在完成替换后,参数不会被允许增长   超过255个字节;这是通过连接尽可能多的来实现的   包含replstr的参数,对于构造的参数   实用程序,最多255个字节。 255字节限制不适用于   实用程序的参数不包含replstr,而且不包含replstr   更换将在实用程序本身完成。意味着-x。

编辑2: 部分解决方案。支持比以前更长的文件名,但仍然没有我需要的时间。

find ./config/pages -name '*.json' -print0 | xargs -0I % sh -c 'file=%; echo Linting: $file; jsonlint -V ./config/schema.json -q $file;'

3 个答案:

答案 0 :(得分:0)

在find中使用-exec而不是管道到xargs。

find ./config/pages -name '*.json' -print0 -exec echo Linting: {} \; -exec jsonlint -V ./config/schema.json -q {} \;

答案 1 :(得分:0)

xargs命令行长度的限制是由系统(而非环境)变量ARG_MAX施加的。您可以像这样检查它:

$ getconf ARG_MAX
2097152

令人惊讶的是,那里有doesn't not seem to be a way to change it, barring kernel modification

但更令人惊讶的是,默认情况下xargs的上限被设置为更低的值,您可以使用-s选项进行增加。尽管如此,ARG_MAX仍不是您可以在-s-acc之后设置的值。到man xargs,您需要减去环境大小,再加上一些“净空”,不知道为什么。要找到实际数字,请使用以下命令(或者,对-s使用任意大数字将导致描述性错误)

$ xargs --show-limits 2>&1 | grep "limit on argument length (this system)"
POSIX upper limit on argument length (this system): 2092120

因此,您需要运行… | xargs -s 2092120 …,例如使用您的命令:

find ./config/pages -name '*.json' -print0 | xargs -s 2092120 -0I % sh -c 'echo Linting: %; jsonlint -V ./config/schema.json -q %;'

答案 2 :(得分:0)

如果您碰巧是在Mac或freebsd等设备上,则您的xargs实现可能支持选项-J,该选项不受选项-I的参数大小限制的影响。

Excert from manpage

-J replstr
If this option is specified, xargs will use the data read from standard input to replace the first occurrence of replstr instead of appending that data after all other arguments. This option will not effect how many arguments will be read from input (-n), or the size of the command(s) xargs will generate (-s). The option just moves where those arguments will be placed in the command(s) that are executed. The replstr must show up as a distinct argument to xargs. It will not be recognized if, for instance, it is in the middle of a quoted string. Furthermore, only the first occurrence of the replstr will be replaced. For example, the following command will copy the list of files and directories which start with an uppercase letter in the current directory to destdir:
/bin/ls -1d [A-Z]* | xargs -J % cp -Rp % destdir

如果您需要多次引用repstr,则可以使用以下模式:

echo hi | xargs -J{} sh -c 'arg=$0; echo "$arg $arg"' "{}"
=> hi hi