【问题标题】:xargs or tail gives error with spaces in directory namesxargs 或 tail 给出目录名称中的空格错误
【发布时间】:2015-10-20 07:18:08
【问题描述】:

我有一个目录结构

Dir 1
Dir 2
Dir 3

,所以每个目录名都包含一个空格。

每个目录都包含文件batch_output.txt。这些文件中的每一个都以标题行开头,然后是下一行的数据。

我想附加这些数据文件,并在顶部附加一次标头(因此标头应该只从第一个文件中提取,而不是重复)。命令

find . -name batch_output.txt -type f

返回 batch_output.txt 文件的路径就好了,但我尝试通过命令附加数据

find . -name batch_output.txt -type f | xargs -n 1 tail -n +2

给我错误

tail: cannot open ‘./Dir’ for reading: No such file or directory
tail: cannot open ‘1/batch_output.txt’ for reading: No such file or directory
tail: cannot open ‘./Dir’ for reading: No such file or directory
tail: cannot open ‘2/batch_output.txt’ for reading: No such file or directory
tail: cannot open ‘./Dir’ for reading: No such file or directory
tail: cannot open ‘3/batch_output.txt’ for reading: No such file or directory

我认为 tail 目录名称中的空格有问题。

在我必须保留目录名中的空格的情况下,我该如何解决这个问题?

【问题讨论】:

    标签: bash find tail xargs


    【解决方案1】:

    xargs 中尝试-print0 选项和-0 选项:

    find . -name batch_output.txt -type f -print0 | xargs -0 -n 1 tail -n +2
    

    根据man find

    -print0
      This primary always evaluates to true. It prints the pathname of the current file 
      to standard output, followed  by an ASCII NUL character (character code 0).
    

    【讨论】:

    • 几乎可以工作。数据附加得很好,但第一个标题丢失了。我想第一次保留标题,但以后不要重复。除此之外,我发现-print0 参数的描述有点不清楚。与没有-print0 的命令相比,为什么它解决了目录名称中的空格问题。 xargs-0 参数究竟做了什么?
    • 不是用换行符终止每个文件名,而是用 ASCII 0 或\0 终止它。 xargs -0 读取以空值结尾的输入数据。
    • 请阅读man xargs 和关于-0 的部分:-0 Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines. This is expected to be used in concert with the -print0 function in find(1).
    【解决方案2】:

    find 使用-exec 参数:

    find . -name batch_output.txt -type f -exec tail -n +2 {} \;
    

    如果你想把输出放到一个新文件中,只需重定向它:

    find . -name batch_output.txt -type f -exec tail -n +2 {} \; > /path/to/outfile
    

    【讨论】:

    • 几乎可以工作。数据附加得很好,但第一个标题丢失了。我想第一次保留标题,但以后不要重复。
    • 在这种情况下,我可能会建议将标题行单独回显到输出文件,并将find 命令的结果附加到>> /path/to/outfile
    【解决方案3】:

    tail 没有得到单引号文件名。对 xargs 使用 -I 参数:

    find . -name batch_output.txt -type f | xargs -I X tail -n +2 X
    

    【讨论】:

      【解决方案4】:

      我相信下面的脚本足够有效。

      #!/bin/bash
      clear
      clear
      
      # Extract first line from the first hit by 'find'.
      find . -name batch_output.txt -type f -print0 -quit | xargs -0 -n 1 head -n 1 > output.txt
      
      # Append all the data after the first line.
      find . -name batch_output.txt -type f -print0 | xargs -0 -n 1 tail -n +2 >> output.txt
      

      【讨论】:

      • 这确实是我在answer 中提供的解决方案。您应该接受答案,而不是采用提供的解决方案并基于此发布另一个答案。
      • @anubhava 嗯……不完全是。您的答案不包括标题的提取,因此我决定发布更完整的答案;)。无论如何,我很感谢你的帮助,我当然不打算从你那里扣留任何学分。如果你愿意,我当然可以接受你的回答。让我知道 ;)。再次感谢!
      • 请看我回答的要点是在find 中使用-print0 和在xargs 中使用-0,因为您遇到了这些错误,这也是您的cmets 所建议的。我只是重用了相同的xargs 命令,假设这对你有用。您可以留下评论,建议您想要更多的头/尾组合,我会编辑我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-19
      相关资源
      最近更新 更多