AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1864471
Accepted
frans
frans
Asked: 2024-12-10 23:55:11 +0800 CST2024-12-10 23:55:11 +0800 CST 2024-12-10 23:55:11 +0800 CST

使用 find + xargs 和嵌套命令进行高级参数转义

  • 772

find ..我知道当您由于“奇怪”的文件名而遇到将例如输出管道传输到的问题时,使用特定的分隔符(例如)来实际传递完整的文件名(例如)xargs会有所帮助。并且,引用有问题的字符串以指定它们的边界“总是”有帮助的。\0find foldername/ -type f -print0 | xargs -0 ...

但是,如果这些字符串(文件名)包含 bash 敏感字符'(如,,,,,".. ?)并且您想使用一个字符串两次(即必须使用,并且需要在嵌套命令中注入这些字符串(即)?`(sh -c .. $(CMD)

例如:

# create a file which should not exist but does
mkdir remove_afterwards
touch remove_afterwards/"some [\"strange\"] ('file')" 

# this will work
find remove_afterwards/ -type f -print0 | xargs -0 -I{} sh -c 'echo "{}"'

# but this won't due to the nested command
find remove_afterwards/ -type f -print0 | xargs -0 -I{} sh -c 'echo "{}" $(stat -c "%s" "{}")'
stat: cannot statx 'remove_afterwards/some [strange] ('\''file'\'')': No such file or directory
remove_afterwards/some [strange] ('file')

我还没弄清楚如何逃离第二个{}里面$()。

有办法吗?

不可否认,一些具有功能的真实脚本会使这一切更容易编写和阅读,但我很好奇,历史上有这样一行代码值得努力去写这个问题。

bash
  • 1 1 个回答
  • 20 Views

1 个回答

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2024-12-11T04:15:38+08:002024-12-11T04:15:38+08:00

    分析

    {}出现问题是因为您在获取的shell 代码中传递了路径名(来自 的扩展) sh -c。sh不知道那里,它获取了已经扩展(通过){}的参数,它将整个字符串解释为 shell 代码。{}xargs

    当嵌入{}到 shell 代码中时,没有固定的方法来引用它扩展为的内容。我的意思是:无论您想让奇怪的路径名如何工作("{}"等等'{}'),我总能想出一个会破坏您的特定代码的路径名;不仅会破坏您的代码,还会注入我的代码。例如,您的代码片段“有效”:

    find remove_afterwards/ -type f -print0 | xargs -0 -I{} sh -c 'echo "{}"'
    

    可以通过创建一个以字面名称命名的文件来利用该漏洞$(beep)(创建此类文件的命令为touch 'remove_afterwards/$(beep)')。很可能beep是无害的,但我本可以使用reboot或rm something。


    解决方案

    安全的方法是将扩展{}作为单独的参数传递,该参数将成为您的位置参数sh -c:

    find remove_afterwards/ -type f -print0 \
    | xargs -0 -I{} sh -c 'echo "$1" "$(stat -c "%s" "$1")"' find-sh {}
    

    (find-sh此处解释:中的第二个 sh 是什么sh -c 'some shell code' sh?)


    解释

    在解决方案中,我们sh -c解释的代码不包含{}刚刚扩展的内容。代码是完全静态的,即事先知道,它就是单引号内的内容。扩展作为位置参数{}传递给,知道它不是代码。无论您在何处需要 shell 代码中的值,都使用。对于外壳来说,重要的是使用单引号或转义,但稍后应该为内壳正确引用(请注意,内壳将看到外壳删除它认为特殊的引号和反斜杠后剩余的引号和反斜杠)。重点是它将自行扩展,仍然知道扩展的值不是 shell 代码。shsh$1$$1sh$1


    更广阔的前景

    在 的情况下也存在同样的问题(有相同的解决方案)find -exec。比较是否可以安全使用find -exec sh -c?

    一般来说,您应该始终选择静态 shell 代码(如果可能*),除非变量部分经过清理或故意设计为解释为 shell 代码。每当您想在 shell 代码中嵌入任何在将要解释代码的 shell“外部”扩展的内容时,这都适用。它不必是{};例如,它可能是一个您想从内部使用的外部变量sh -c:

    # flawed: embedding in shell code
    var="I want to print '"'$(beep)'"'"
    sh -c "echo '$var'"
    
    # right: passing as positional parameter
    var="I want to print '"'$(beep)'"'"
    sh -c 'echo "$1"' sh "$var"
    
    # also right: passing in environment
    var="I want to print '"'$(beep)'"'"
    var="$var" sh -c 'echo "$var"'
    

    * 构建静态 shell 代码并非总是可行的。例如,通过 运行的命令ssh始终是单个字符串,由远程 shell 解释为 shell 代码;因此,如果您需要传递局部变量的值,那么除了将其嵌入 shell 代码之外别无他法。但仍有方法可以正确执行此操作(对于 Bash:请参阅${parameter@operator}运算符何时为Q)。


    暗示

    如果您选择为 构建静态 shell 代码sh -c,我建议对整个代码使用单引号。唯一“有问题”的字符将是单引号本身(如果您需要它属于 shell 代码参数)。您可能会发现这很有用:如何方便地在 Bash 中对整个命令行使用单引号或转义?

    • 1

相关问题

  • 在非 root 用户上用 bash 替换 zsh

  • 在 macOS High Sierra 的终端中设置环境变量时遇到问题

  • 对于 cp 或 mv,是否有等同于 cd - 的东西?

  • Notify-发送窗口下出现的通知

  • 如何从 WSL 打开 office 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何减少“vmmem”进程的消耗?

    • 11 个回答
  • Marko Smith

    从 Microsoft Stream 下载视频

    • 4 个回答
  • Marko Smith

    Google Chrome DevTools 无法解析 SourceMap:chrome-extension

    • 6 个回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Martin Hope
    Vickel Firefox 不再允许粘贴到 WhatsApp 网页中? 2023-08-18 05:04:35 +0800 CST
  • Martin Hope
    Saaru Lindestøkke 为什么使用 Python 的 tar 库时 tar.xz 文件比 macOS tar 小 15 倍? 2021-03-14 09:37:48 +0800 CST
  • Martin Hope
    CiaranWelsh 如何减少“vmmem”进程的消耗? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Windows 10 搜索未加载,显示空白窗口 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve