6

我正在使用 jsonlint 对目录中的一堆文件进行 lint(递归)。我写了以下命令:

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 的实用程序参数,此外,不会对实用程序本身进行替换。暗示-x。

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

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

4

3 回答 3

5

在类似 BSD 的系统上(例如 Mac OS X)

如果您碰巧在 mac 或 freebsd 等设备上,您的xargs实现可能支持 option-J不受 option 的参数大小限制的影响-I

来自手册页的摘录

-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多次引用(*指向* TL;DR-J仅替换第一次出现),您可以使用此模式:

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

符合 POSIX 的方法

执行此操作的 posix 兼容方法是使用其他工具,例如sed构造您要执行的代码,然后用于xargs指定实用程序。当 xargs 中没有使用 repl 字符串时,255 字节的限制不适用。xargs POSIX 规范

find . -type f -name '*.json' -print |
  sed "s_^_-c 'file=\\\"_g;s_\$_\\\"; echo \\\"Definitely over 255 byte script..$(printf "a%.0s" {1..255}): \\\$file\\\"; wc -l \\\"\\\$file\\\"'_g" |
  xargs -L1 sh

这当然在很大程度上违背了xargs开始的目的,但仍然可以用来利用例如并行执行xargs -L1 -P10 sh,虽然不是 posix,但它得到了相当广泛的支持。

于 2019-04-02T10:57:11.623 回答
1
于 2018-07-30T11:57:01.643 回答
0

在 find 中使用-exec而不是通过管道连接到 xargs。

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

于 2017-08-09T15:43:22.083 回答