bash - 如果已使用单引号和双引号,则 find -exec 的解决方案

标签 bash shell find double-quotes

我想递归地遍历所有子目录并删除每个名为“bak”的子文件夹中最旧的两个 PDF:

作品:

find . -type d -name "bak" \
  -exec bash -c "cd '{}' && pwd" \;

不起作用,因为双引号已在使用中:

find . -type d -name "bak" \
  -exec bash -c "cd '{}' && rm "$(ls -t *.pdf | tail -2)"" \;

有什么办法可以解决双引号难题吗?

最佳答案

在双引号字符串中,您可以使用反斜杠来转义其他双引号,例如

find ... "rm \"\$(...)\""

如果这太复杂,请使用变量:

cmd='$(...)'
find ... "rm $cmd"

但是,我认为你的find -exec问题还不止这些。

  • 使用{}命令字符串 "cd '{}' ..." 内有风险。如果有'在文件名内,事情将会中断并可能执行意外的命令。
  • $() find之前将被bash扩展甚至运行。所以ls -t *.pdf | tail -2只会在顶层目录 . 执行一次而不是每个找到的目录一次。 rm将(尝试)删除每个找到的目录的相同文件。
  • rm "$(ls -t *.pdf | tail -2)"如果 ls 将不起作用列出多个文件。由于引号的存在,两个文件都将在一个参数中列出。因此,rm会尝试删除一个名为 first.pdf\nsecond.pdf 的文件.

我建议

cmd='cd "$1" && ls -t *.pdf | tail -n2 | sed "s/./\\\\&/g" | xargs rm'
find . -type d -name bak -exec bash -c "$cmd" -- {} \;

关于bash - 如果已使用单引号和双引号,则 find -exec 的解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65741244/

相关文章:

bash - 如何从脚本向脚本发送信号 SIGINT?

linux - 我的 Linux 系统无法识别主机名。我该如何解决?

linux - 通过读取命令在 POSIX 兼容的 shell 脚本中解析 cal 输出

linux - 如何将值传递给另一个代码以在 linux 中执行进程

php - Shell 脚本 "read"函数 - 不是有效的标识符

shell - 如何否定/"reverse mean"这个搜索——也就是 "!"的意思

bash - 尝试 rm 时如何处理缺少操作数错误

双重访问查找操作所需的结构的 C++ 容器

linux - 加速/并行化大规模硬链接(hard link)循环

bash - expr 显示表达式而不是求解它