【问题标题】:Using touch and sed within a find -ok command在 find -ok 命令中使用 touch 和 sed
【发布时间】:2017-04-01 17:11:41
【问题描述】:

我有一些 wav 文件。对于这些文件中的每一个,我想创建一个具有相同名称的新文本文件(显然 wav 扩展名被替换为 txt)。

我第一次尝试这个:

find . -name *.wav -exec 'touch $(echo '{}" | sed -r 's/[^.]+\$/txt/')" \;

哪个输出了

?

然后 find 在我按下 y 键后抱怨:

find: 'touch $(echo ./music.wav | sed -r 's/[^.]+$/txt/')': 没有这样的文件或目录

我发现我正在使用管道并且实际上需要一个外壳。然后我跑了:

find . -name *.wav -exec sh -c 'touch $(echo "'{}"\" | sed -r 's/[^.]+\$/txt/')" \;

谁做的。

实际上,我并没有真正了解内部正在做什么,但我猜每个文件都会生成一个 shell,对吧?我担心这会耗费大量内存。
那么,如果我需要在一大堆文件和目录上运行这个命令怎么办!?

现在有没有更有效的方法来做到这一点?
基本上我需要转换当前文件的名称并提供触摸命令。

谢谢。

【问题讨论】:

    标签: bash find exec


    【解决方案1】:

    这个findbash parameter-expansion 将为您解决问题。你根本不需要sed

    find . -type f -name "*.wav" -exec sh -c 'x=$1; file="${x##*/}"; woe="${file%.*}"; touch "${woe}.txt"; ' sh {} \;
    

    想法是一部分

    • x=$1 表示从 find 的输出返回的每个条目
    • file="${x##*/}" 去除文件路径,只留下最后一个文件名部分(仅filename.ext
    • woe="${file%.*}" 部分存储不带扩展名的名称,并根据找到的名称创建带有扩展名 .txt 的新文件。

    编辑

    参数扩展让我们免于使用命令替换$()子进程和sed
    在查看 sh 手册页后,我发现上面的命令可以简化。

    概要 -c [-aCefnuvxIimqVEbp] [+aCefnuvxIimqVEbp] [-o option_name] [+o option_name] command_string [command_name [参数 ...]]
    ...
    -ccommand_string 操作数而不是从标准输入中读取命令。 特殊参数 0 将由 command_name 操作数设置,位置参数($1、$2 等)将从其余 argument 操作数设置.

    我们可以直接传递文件路径,跳过 shell 的名称(无论如何这在脚本中是无用的)。所以{} 作为command_name $0 传递,可以立即展开。
    我们最终得到了一个更简洁的命令。

    find . -name *.wav -exec sh -c 'touch "${0%.*}".txt ;' {} \;
    

    【讨论】:

    • 这是一个很好的改进,我没有想到参数扩展。有什么更轻的想法吗?
    • @Stphane:这比sed 更可靠,可以更好地控制我们对每个输入的操作以及操作的发生方式。不过我个人更喜欢这种方式!
    • 你至少应该得到 +1,我会让这个问题再存活一两天,以便发布其他答案。如果在此期间没有其他人提交更好的答案,我会选择你的:)
    猜你喜欢
    • 2015-12-02
    • 2017-04-14
    • 2016-11-09
    • 1970-01-01
    • 2014-02-23
    • 2019-11-24
    • 2014-08-03
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多