【问题标题】:How to use > in an xargs command?如何在 xargs 命令中使用 >?
【发布时间】:2010-10-25 03:45:09
【问题描述】:

我想找到一个 bash 命令,它可以让我 grep 目录中的每个文件并将该 grep 的输出写入单独的文件。我的猜测是做这样的事情

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

但是,据我所知,xargs 不喜欢双引号。但是,如果我删除双引号,那么该命令会将整个命令的输出重定向到一个名为 '{}'.out 的文件,而不是一系列单独的文件。

有人知道使用 xargs 的方法吗?我只是以这个 grep 场景为例来说明我的 xargs 问题,因此任何不使用 xargs 的解决方案都不适用于我。

【问题讨论】:

    标签: bash redirect xargs


    【解决方案1】:

    不要犯这样的错误:

    sh -c "grep ABC {} > {}.out"
    

    这会在很多情况下中断,包括时髦的文件名并且不可能正确引用。您的 {} 必须始终是命令的一个完全独立的参数,以避免代码注入错误。你需要做的是:

    xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
    

    适用于xargsfind

    顺便说一句,不要在没有 -0 选项的情况下使用 xargs(除非您不担心破坏数据的非常罕见且受控的一次性交互使用)。

    也不要解析ls。曾经。请改用通配符或findhttp://mywiki.wooledge.org/ParsingLs

    对需要递归的所有内容使用find,对其他所有内容使用带有glob 的简单循环:

    find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;
    

    或非递归:

    for file in *; do grep "$file" > "$file.out"; done
    

    注意正确使用引号。

    【讨论】:

    • @legends2k 因为当您不使用-0 时,xargs 将使用您的文件名并破坏其中的所有空格、引号和反斜杠。您应该忘记 xargs 作为工具。如果有行,请使用 bash 循环来迭代行:while read line; do <command> "$REPLY"; done < file-with-linescommand | while ...
    • 哇,不知道,感谢您提供的详细信息!所以为了可移植性(因为不是所有的xargs 都是GNU 的),需要避免xargs,除非可以将它与-0 一起使用。谢谢。
    • 虽然我很欣赏对这个特定用例的详细解释,但问题是关于重定向xargs 的输出,这并不总是涉及解析ls 或使用sh -c。这丝毫没有回答问题,而是该问题的第一个谷歌结果,只会增加混乱。
    • @pandasauce 再次阅读了问题的第一句话。这是回答的。此外,答案中的第二个代码引用正是您要查找的内容,并且不特定于 ls。如果有帮助,我已经稍微修改了答案以使其更清楚。
    • @Ihunath,您好,您的回答对我很有效。但是你能给出一些关于xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}的详细解释或链接吗?特别是嵌入(双)引号的规则和末尾的“--”符号。谢谢
    【解决方案2】:

    没有xargs 的解决方案如下:

    find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
    

    ...同样可以使用 xargs,结果是:

    ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
    

    编辑lhunath 备注后添加单引号。

    【讨论】:

    • 他说他想使用 xargs。我也发布了一个没有它的解决方案,但是一旦我看到他需要 xargs 就删除了。
    • 你是对的。我发布答案的原因是有一个替代解决方案来完成工作总比没有好。事实证明,它让我找到了想要的答案(即 sh -c 技巧)。
    【解决方案3】:

    我假设您的示例只是一个示例,您可能需要 > 来处理其他事情。 GNU Parallel http://www.gnu.org/software/parallel/ 可能是您的救星。只要您的文件名不包含 \n:

    ,它就不需要额外的引用
    ls | parallel "grep ABC {} > {}.out"
    

    如果您的文件名中包含 \n:

    find . -print0 | parallel -0 "grep ABC {} > {}.out"
    

    作为额外的奖励,您可以并行运行作业。

    观看介绍视频以了解更多信息:http://pi.dk/1

    10 秒安装将尝试进行完整安装;如果失败,个人安装;如果失败,则进行最小安装:

    $ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
       fetch -o - http://pi.dk/3 ) > install.sh
    $ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
    12345678 883c667e 01eed62f 975ad28b 6d50e22a
    $ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
    cc21b4c9 43fd03e9 3ae1ae49 e28573c0
    $ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
    79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
    fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
    $ bash install.sh
    

    如果您需要将其移至未安装 GNU Parallel 的服务器,请尝试 parallel --embed

    【讨论】:

      【解决方案4】:

      实际上,这里的大多数答案都不适用于所有文件名(如果它们包含双引号和单引号),包括 lhunath 和 Stephan202 的答案。

      此解决方案适用于带有单引号和双引号的文件名:

      find . -mindepth 1 -print0 | xargs -0 -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
      

      这是一个带有单引号和双引号的文件名的测试:

      echo ABC > "I'm here.txt"
      
      # lhunath solution (hangs waiting for input)
      
      $ find . -exec sh -c 'grep "$1" > "$1.out"' -- {} \;
      
      # Stephan202 solutions
      
      $ find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;
      grep: ./Im: No such file or directory
      grep: here.txt > ./Im here.txt.out: No such file or directory
      
      $ ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"
      xargs: unterminated quote
      
      # this solution
      $ find . -mindepth 1 -print0 | xargs -0 -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}
      
      $ ls -1
      "I'm here.txt"
      "I'm here.txt.out"
      

      【讨论】:

        猜你喜欢
        • 2017-11-15
        • 2010-11-02
        • 1970-01-01
        • 1970-01-01
        • 2022-08-22
        • 1970-01-01
        • 1970-01-01
        • 2020-03-31
        • 1970-01-01
        相关资源
        最近更新 更多