【问题标题】:Elixir shell command with wildcard failing when using System.cmd使用 System.cmd 时带有通配符的 Elixir shell 命令失败
【发布时间】:2018-04-28 03:23:33
【问题描述】:

我有一个 elixir 程序,它需要以编程方式删除可变数量的这样命名的 PNG 文件。

/path/to/dir/<uuid>-frames-001.png
/path/to/dir/<uuid>-frames-002.png
/path/to/dir/<uuid>-frames-003.png

等等

自然而然,我想出了下面的万能药代码来删除这些文件。

System.cmd("rm", ["/path/to/dir/" <> uuid <> "-frames-*.png"])

我已经看到上面的代码以多种方式失败。首先,我在服务器上运行它并看到了以下堆栈跟踪:

/bin/rm: cannot remove '/path/to/dir/<uuid>-frames-*.png': No such file or directory

我还在控制台会话上运行了这段代码,看到了完全相同的输出。

如果我在 bash 会话中运行以下命令,它可以正常工作!

rm /path/to/dir/&lt;uuid&gt;-frames-*.png

它返回一个0 错误代码并删除预期的文件。似乎 elixir 将 * 解释为文字字符,而不是执行预期的通配符删除。知道如何做到这一点吗?谢谢!

附言

很明显,&lt;uuid&gt; 是一个实际的 uuid,因此不应从字面上解释这个问题的范围。

【问题讨论】:

标签: elixir phoenix-framework


【解决方案1】:

* 这样的通配符由shell 扩展,而不是rm。您的命令只会删除字面上称为 /path/to/dir/&lt;uuid&gt;-frames-*.png 的文件。

您可以通过将命令传递给 sh 之类的 shell 来扩展通配符:

System.cmd("/bin/sh", ["-c", "rm /path/to/dir/#{uuid}-frames-*.png"])

或使用os:cmd/1 默认调用sh(注意单引号而不是双引号):

:os.cmd('rm /path/to/dir/#{uuid}-frames-*.png')

【讨论】:

    【解决方案2】:

    第二个参数中的路径调用System.cmd/2“可执行文件将接收作为其参数的二进制文件列表原样。”来自the documentation

    这意味着:

    ——环境变量不会被插值
    不会发生通配符扩展(除非明确使用Path.wildcard/2
    — 为了 shell 安全,不需要对参数进行转义或引用。

    所以,要使用通配符,应该:

    System.cmd("rm", Path.wildcard("/path/to/dir/" <> uuid <> "-frames-*.png"))
    

    注意,由于Path.wildcard/2 已经返回了一个列表,所以不应该再次包装它。

    还有许多其他解决方法,但对于这种特殊情况,只需使用 File.rm/1

    【讨论】:

    • 感谢您提供有关 Path.wildcard 的信息。您能否详细说明您对使用File.rm/1“针对这种特殊情况”的评论? File.rm 不扩展通配符,那么你的策略是什么?
    猜你喜欢
    • 2016-11-19
    • 2017-09-11
    • 2016-08-08
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    相关资源
    最近更新 更多