在 find -ok 命令中使用 touch 和 sed

Using touch and sed within a find -ok command

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

我第一次尝试这个:

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

输出了

< touch $(echo {} | sed -r 's/[^.]+$/txt/') ... ./The_stranglers-Golden_brown.wav > ?

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

find: ‘touch $(echo ./music.wav | sed -r 's/[^.]+$/txt/')’: No such file or directory

我发现我使用的是管道,实际上需要一个 shell。然后我 运行:

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

哪个做的。

实际上,我并没有真正了解内部正在做什么,但我想每个文件都会产生一个 shell 对吗?我担心这会占用大量内存。
然后,如果我需要对一大堆文件和目录执行 运行 这个命令怎么办!?

现在有没有更有效的方法来做到这一点?
基本上我需要 t运行sform 当前文件的名称并输入 touch 命令。

谢谢。

这个 findbash 参数扩展 将为您解决问题。你根本不需要 sed

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

想法是关键

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

编辑

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

Synopsis -c [-aCefnuvxIimqVEbp] [+aCefnuvxIimqVEbp] [-o option_name] [+o option_name] command_string [command_name [argument ...]]
...
-c Read commands from the command_string operand instead of from the stan‐dard input. Special parameter 0 will be set from the command_name oper‐and and the positional parameters (, , etc.) set from the remaining argument operands.

我们可以直接传递文件路径,跳过 shell 的名称(反正在脚本中是无用的)。因此 {} 作为 command_name [=23=] 传递,可以立即展开。
我们最终得到了一个更清晰的命令。

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