在 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 命令。
谢谢。
这个 find
和 bash
参数扩展 将为您解决问题。你根本不需要 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 ;' {} \;
我有一些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 命令。
谢谢。
这个 find
和 bash
参数扩展 将为您解决问题。你根本不需要 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 ;' {} \;