Elixir中System.cmd执行带通配符的rm命令失败问题
解决Elixir中批量删除带通配符PNG文件的问题
我懂你碰到的麻烦了——用System.cmd("rm", ["/path/to/dir/" <> uuid <> "-frames-*.png"])删除文件总是失败,核心问题其实是Elixir的System.cmd默认不会通过shell执行命令,你写的*通配符根本不会被解析展开,rm会把整个带*的字符串当成一个单独的文件名去找,自然找不到对应的文件。
下面给你几个靠谱的解决方案,按安全性和易用性排序:
方案1:用Elixir原生文件API(最安全推荐)
直接用Elixir的Path.wildcard匹配所有符合模式的文件,再逐个删除,完全不需要依赖shell,也避免了shell注入的风险(如果uuid是用户输入的话这点尤其重要):
# 匹配所有符合格式的PNG文件 files_to_delete = Path.wildcard("/path/to/dir/#{uuid}-frames-*.png") # 逐个删除,File.rm会返回{:ok, _}或{:error, reason},可以按需处理结果 Enum.each(files_to_delete, fn file -> case File.rm(file) do :ok -> IO.puts("成功删除文件:#{file}") {:error, reason} -> IO.puts("删除文件失败 #{file}:#{inspect(reason)}") end end) # 如果想强制删除(忽略不存在的文件或权限问题时直接抛出异常),可以用File.rm!/1 # Enum.each(files_to_delete, &File.rm!/1)
方案2:让System.cmd通过shell执行
如果你更习惯用shell命令,可以给System.cmd加上shell: true选项,这样shell会帮你展开通配符。但要注意:如果uuid包含特殊字符(比如空格、引号)或者来自不可信的用户输入,这种方式可能会有shell注入风险,一定要确保uuid是安全的(比如是标准UUID格式,没有特殊字符):
System.cmd("rm", ["/path/to/dir/#{uuid}-frames-*.png"], shell: true)
方案3:先匹配文件再传给rm命令
和方案1类似,但用rm批量删除,适合需要一次性传递所有文件给rm的场景:
files = Path.wildcard("/path/to/dir/#{uuid}-frames-*.png") # 如果文件列表为空,rm会报错,所以可以加个判断避免无意义的调用 if length(files) > 0 do System.cmd("rm", files) end
额外排查点
如果还是失败,可以检查这几点:
- 确认
/path/to/dir/路径正确,程序拥有该目录的读写权限 - 确认
uuid拼接后路径正确,比如有没有多了或少了斜杠 - 检查服务器上的文件是否真的存在,类Unix系统要注意文件名大小写区分问题
内容的提问来源于stack exchange,提问作者Kulix
相关产品推荐
相关产品推荐

