通过exec在find的输出上进行Bash变量替换

7

有没有办法在find的输出中应用Bash变量替换?我知道我曾经在Stack Overflow上看到过有人这样做,但现在好像找不到那篇帖子了。

例如,假设我想将以*.png结尾的文件重命名为*_copy.png。 我知道我可以使用rename来完成这个任务,但这只是一个思考实验。

现在我想要做这样的事情:

find . -name "*png" -exec mv "{}" "${{}%.*}_copy.png" \;

这将导致一个无效的替换。当然,我可以先将输出赋值给一个变量,然后在子shell中应用替换,但这真的是唯一的方法吗?
find . -name "*.png" -exec bash -c 'var="{}";  mv "{}" "${var%.*}_copy.png"' \;

还是有没有办法直接从{}实现这个目标呢?

共识

正如Etan Reisner所指出的那样,处理find的输出更好、更安全的方法是将其作为位置参数传递:

find . -name "*.png" -exec bash -c 'mv "$0" "${0%.*}_copy.png"' "{}" \;

将答案(甚至共识摘要)编辑到问题中是不被赞同的,因为这会使该答案免于正常的审查、投票和其他基于社区的管理。如果您想要一个建立在他人工作基础上的答案,而又不想以自己的名义/获得声望,请考虑添加一个标记为“社区维基”的答案。 - Charles Duffy
1个回答

3
我需要一些时间来理解这个问题。基本上你在问是否像这样的东西:
echo "${test.png%.png}"

可以用来获取单词test

答案是否定的。以${开始的字符串操作符参数替换操作符的子集。它们只能在变量上工作,而不能对字符串文字进行操作,这意味着您需要先将字符串存储在变量中。像这样:

img="test.png"
echo "${img%.png}"

针对来自Google的旅行者,我建议在这个特定任务中使用rename命令(正如原帖中提到的一样)。该命令可能如下所示:

find -name '*png' -execdir rename 's/\.png/_copy.png/' {} +

抱歉,疏忽了。让我用bash添加一个示例。 - hek2mgl
不用担心,我在 Stack Overflow 上也经常会忽略一些东西,哈哈。 - ShellFish
@ShellFish,您无需引用{},因为它不会成为单词拆分的对象。 - hek2mgl
哦,真的吗?哇,那我在我的生活中引用了太多 {} 了。谢谢你的提示! - ShellFish
4
作为一个附带说明,你 绝不能 直接嵌入 {} 在使用 sh -c 或类似方式运行的 shell 脚本中。这对于空格等内容来说是不安全的(引号也无法解决这个问题,它只会将问题转移到引号转义上)。相反,你应该将其作为位置参数传递给脚本。 - Etan Reisner
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接