如果Ruby不存在,则创建目录


156

我正在尝试使用以下代码创建目录:

Dir.mkdir("/Users/Luigi/Desktop/Survey_Final/Archived/Survey/test")
    unless File.exists?("/Users/Luigi/Desktop/Survey_Final/Archived/Survey/test")  

但是,我收到此错误:

没有这样的文件或目录-/ Users / Luigi / Desktop / Survey_Final / Archived / Survey / test(Errno :: ENOENT)

为什么Dir.mkdir上面的语句没有创建该目录?


4
File.exists?()适用于文件和文件夹。它不知道区别。
Tin Man

Answers:


263

您可能正在尝试创建嵌套目录。假设foo不存在,您将收到以下no such file or directory错误:

Dir.mkdir 'foo/bar'
# => Errno::ENOENT: No such file or directory - 'foo/bar'

要立即创建嵌套目录,FileUtils需要:

require 'fileutils'
FileUtils.mkdir_p 'foo/bar'
# => ["foo/bar"]

Edit2:您不必使用FileUtils,您可以进行系统调用(从@mu更新太短的注释):

> system 'mkdir', '-p', 'foo/bar' # worse version: system 'mkdir -p "foo/bar"'
=> true

但这(至少对我而言)似乎是使用外部“工具”的更糟糕的方法,这种方法在某些系统上可能不可用(尽管我很难想象没有mkdir,但是谁知道)。


5
system 'mkdir', '-p', 'foo/bar'会是该system电话的更好版本。不需要额外的shell流程,也不需要使用单个参数版本附带的通常的引用/转义/注入废话system
亩太短,

6
system将启动/bin/sh以分析mkdir -p "foo/bar"字符串,然后外壳程序将运行/bin/mkdir。因此,您需要做更多的工作(创建命令字符串,启动/bin/sh以再次将其拆开),其中一些额外的工作使您容易受到外壳注入攻击的影响(在Ruby的CERT咨询中花了一些时间,您会发现它多么常见。这个问题是)。
亩太短,

1
@muistooshort @ zrl3dx system通话效果如何fileutils?我在Windows上,并且mkdir_p可以正常工作而不会产生仅用于解析的shell,否则mkdir -p无论如何它将失败。很高兴这fileutils是答案中的第一个选择。
TWiStErRob

1
@TWiStErRob:再次阅读我的意见,我说一无所知fileutils或者mkdir_p,我想说的是,system command, arg1, arg2, ...优于system command_with_arguments
亩太短了

3
@muistooshort啊,对不起,所以您只是说有一种更好的方法来执行错误的选择:)
TWiStErRob

71

简单方法:

directory_name = "name"
Dir.mkdir(directory_name) unless File.exists?(directory_name)

8
一个应该使用File.directory吗?而不是File.exists?
FlorinAsăvoaie2015年

4
假设有一个同名的普通文件。在这种情况下,您将无法创建目录。
MikołajRozwadowski

3
它还会创建竞争条件。该文件可以在检查之后但在创建之前创建。
Don Reba

25

另一个简单的方法:

Dir.mkdir('tmp/excel') unless Dir.exist?('tmp/excel')


如果要创建嵌套目录,则此方法无效。例如,我想创建以下目录,/home/jignesh/reports/test但使用此解决方案RUBY (Errno::ENOENT), no such file or directory @ dir_s_mkdir。因此,可靠的解决方案是使用FileUtils.mkdir_p
Jignesh Gohel

-5

怎么样Dir.mkdir('dir') rescue nil


3
避免rescue以其修饰符形式使用。
塞巴斯蒂安·帕尔玛

1
努力解释为什么我应该写5行代码而不是1行?我想看看你试试。
维达尔


1
我已经做了,但我完全不同意,我认为这很愚蠢,所以也许您可以启发我?
维达尔

6
这将捕获任何不是您要尝试执行的异常,并且在现实世界中的应用程序中会隐藏使维护难度加大的问题。同样,使用异常作为条件语句不是一个好主意,从硬件的角度来看,它们的运行速度要慢得多(在现代语言中这可能不是真正的问题,但仍然会让您缺乏编码经验。)
Ed_
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.