【问题标题】:Can find push the filenames of the found files into the pipe?find 可以将找到的文件的文件名推送到管道中吗?
【发布时间】:2016-09-23 00:55:13
【问题描述】:

我想在一些dir中查找,并在此目录中的文件上查找awk,然后用每个结果替换原始文件。

find dir | xargs cat | awk ... | mv ... > filename

所以我需要最后一个命令中的文件名(find 找到的每个文件)。我该怎么做?

【问题讨论】:

  • 你遇到了什么问题?
  • 编写一个脚本并传递文件名 find dir -exec myscript {} \;,其中 myscript 以 name="$1" 开头,并且是 cat、awk 等。
  • xargs cat 这里没有意义(并且不会工作,因为它会合并文件)。 xargs awk 会更好(并且会让awk 独立处理每个文件,如果你真的想要,包括运行mv)。
  • 您希望在哪里使用这种管道从awk 写入内容?您需要一个文件供mv 操作(并且它不会从标准输入读取。您可以awk(使用xargs awk)写入一个临时文件,然后让它将新旧名称打印到标准输出,然后使用xargs mv(每个命令限制为两个条目)但这太复杂了。

标签: linux bash gnu-findutils


【解决方案1】:

可以做这样的事情(但我一点也不推荐)。

find dir -print0 |
    xargs -0 -n 2 awk -v OFS='\0' '<process the input and write to temporary file>
        END {print "temporaryfile", FILENAME}' |
    xargs -0 -n 2 mv

这会将文件一次直接两个传递给awk(这避免了您的原始问题,cat 将同时获得数百个(可能更多)文件作为参数并吐出 all 他们在awk 的内容一次通过标准输入,因此完全丢失了他们各自的内容和文件名。

然后它让awk 将处理后的输出写入一个临时文件,然后输出临时文件名和原始文件名,xargs 将它们拾取(一次两次)并在临时文件/原始文件名。

正如我在开始时所说的那样,这是一种糟糕的方式。

如果您有足够新的GNU awk 版本(4.1.0 或更高版本),那么您可以使用-i(就地)参数到awk 并使用(我相信):

find dir | xargs awk -i '......'

否则,我将使用Bash FAQ 001 中的while 循环来逐行读取find 输出并在循环中对其进行操作。

【讨论】:

    【解决方案2】:

    我会使用循环,例如:

    for filename in `find . -name "*test_file*" -print0 | xargs -0`
    do
        # some processing, then
        echo "what you like" > "$filename"
    done
    

    编辑:如 cmets 所述,-print0 | xargs -0 的好处因for 循环而丧失。并且包含空格的文件名仍然无法正确处理。

    以下while 循环也不会处理不寻常的文件名(很高兴知道它,虽然它不是问题),但至少具有标准空白的文件名,因此它确实更好地工作:

    find . -name "*test*file*" -print > files_list
    
    while IFS= read -r filename
    do
        # some process
        echo "what you like" > "$filename"
    done < files_list
    

    【讨论】:

    • 我知道,但我想知道您是否可以通过find dir 开始而不是for f in $(find dir) 来做到这一点
    • 也许您可以在您的问题中添加这种精确度?如果不将文件名存储在某处,我不知道如何在几个命令后将它们取回。
    • find dir | while read filename 的行为非常相似,并且 确实 以 find dir 开头 - 但 zezollos 的答案涵盖了案例,例如文件名中的换行符不会被这个处理 - 但没有人真正理解你为什么热衷于“以find dir开头”
    • 这个答案确实 not 处理名称中带有换行符/空格等的文件名。你从-print0-0 获得的任何安全性,使用for filename in `...` 会立即失去(甚至更糟)。因为你不应该read lines with for
    • @EtanReisner ...并重定向到未引用的$filename
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 2019-03-12
    相关资源
    最近更新 更多