如何在 C++ 中创建目录树 在 Linux 上?
我想要一种在 Linux 上用 C++ 创建多个目录的简单方法。
例如,我想在目录中保存文件 lola.file:
/tmp/a/b/c
但如果目录不存在,我希望自动创建它们。 一个有效的例子就完美了。
I want an easy way to create multiple directories in C++ on Linux.
For example, I want to save a file lola.file in the directory:
/tmp/a/b/c
but if the directories are not there I want them to be created automagically. A working example would be perfect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
轻松使用 Boost.Filesystem:
create_directories< /code>
返回:如果创建了新目录,则返回
true
,否则返回false
。Easy with Boost.Filesystem:
create_directories
Returns:
true
if a new directory was created, otherwisefalse
.对于 C++17 或更高版本,标准标头
包含功能
std::filesystem::create_directories
应该在现代 C++ 程序中使用。
C++ 标准函数没有 POSIX 特定的显式
不过,权限(模式)参数。
然而,这里有一个可以用 C++ 编译器编译的 C 函数。
宏
STRDUP()
和FREE()
是错误检查版本strdup()
和free()
,在emalloc.h
中声明(并在emalloc.c
和estrdup.c
)。"sysstat.h"
标头处理
的损坏版本在现代 Unix 系统上可以用
替换(但是有早在 1990 年就有很多问题)。
"mkpath.h"
声明mkpath()
。v1.12(答案的原始版本)和v1.13之间的变化
(答案的修改版本)是对
EEXIST
的测试do_mkdir()
。指出这是必要的
切换 — 谢谢
你,开关。
测试代码已升级,在MacBook上重现问题
Pro(2.3GHz Intel Core i7,运行 Mac OS X 10.7.4),并建议
问题在修订版中得到解决(但测试只能显示
存在错误,而不是不存在)。
显示的代码现在是 v1.16; 有化妆品或行政
自 v1.13 以来所做的更改(例如使用
mkpath.h
代替jlss.h
以及仅在测试代码中无条件包含
)。有理由认为
"sysstat.h"
应该替换为
除非您的系统异常顽固。(特此授权您将此代码用于任何目的并注明出处。)
此代码可在我的 SOQ
(堆栈溢出问题)GitHub 上的存储库作为文件
mkpath.c
和mkpath.h
(等)在src/so-0067-5039
子目录。
With C++17 or later, there's the standard header
<filesystem>
withfunction
std::filesystem::create_directories
which should be used in modern C++ programs.
The C++ standard functions do not have the POSIX-specific explicit
permissions (mode) argument, though.
However, here's a C function that can be compiled with C++ compilers.
The macros
STRDUP()
andFREE()
are error-checking versions ofstrdup()
andfree()
, declared inemalloc.h
(and implemented inemalloc.c
andestrdup.c
).The
"sysstat.h"
header deals with broken versions of<sys/stat.h>
and can be replaced by
<sys/stat.h>
on modern Unix systems (but therewere many issues back in 1990).
And
"mkpath.h"
declaresmkpath()
.The change between v1.12 (original version of the answer) and v1.13
(amended version of the answer) was the test for
EEXIST
indo_mkdir()
.This was pointed out as necessary by
Switch — thank
you, Switch.
The test code has been upgraded and reproduced the problem on a MacBook
Pro (2.3GHz Intel Core i7, running Mac OS X 10.7.4), and suggests that
the problem is fixed in the revision (but testing can only show the
presence of bugs, never their absence).
The code shown is now v1.16; there have been cosmetic or administrative
changes made since v1.13 (such as use
mkpath.h
instead ofjlss.h
andinclude
<unistd.h>
unconditionally in the test code only).It's reasonable to argue that
"sysstat.h"
should be replaced by<sys/stat.h>
unless you have an unusually recalcitrant system.(You are hereby given permission to use this code for any purpose with attribution.)
This code is available in my SOQ
(Stack Overflow Questions) repository on GitHub as files
mkpath.c
andmkpath.h
(etc.) in thesrc/so-0067-5039
sub-directory.
是我能想到的最短的方法(就代码长度而言,不一定是执行时间)。
它不是跨平台的,但可以在 Linux 下工作。
is the shortest way I can think of (in terms of the length of code, not necessarily execution time).
It's not cross-platform but will work under Linux.
这是我的代码示例(适用于 Windows 和 Linux):
用法:
Here is my example of code (it works for both Windows and Linux):
Usage:
来自此处。 您可能必须对 /tmp、/tmp/a、/tmp/a/b/ 和 /tmp/a/b/c 分别执行 mkdirs,因为 C api 中没有与 -p 标志等效的选项。 当您执行更高级别的错误时,请务必忽略 EEXISTS errno。
From here. You may have to do separate mkdirs for /tmp, /tmp/a, /tmp/a/b/ and then /tmp/a/b/c because there isn't an equivalent of the -p flag in the C api. Be sure and ignore the EEXISTS errno while you're doing the upper level ones.
需要注意的是,从C++17开始,文件系统接口是标准库的一部分。 这意味着可以通过以下方式创建目录:
更多信息请参见:https://en。 cppreference.com/w/cpp/filesystem/create_directory
此外,使用 gcc,需要将“-std=c++17”添加到 CFLAGS。 以及 LDLIBS 的“-lstdc++fs”。 将来可能不需要后者。
It should be noted that starting from C++17 filesystem interface is part of the standard library. This means that one can have following to create directories:
More info here: https://en.cppreference.com/w/cpp/filesystem/create_directory
Additionally, with gcc, one needs to "-std=c++17" to CFLAGS. And "-lstdc++fs" to LDLIBS. The latter potentially is not going to be required in the future.
这与前一个类似,但通过字符串向前而不是向后递归。 为上次失败保留正确的 errno 值。 如果有前导斜杠,则循环会花费额外的时间,这可以通过循环外的 find_first_of() 或通过检测前导 / 并将 pre 设置为 1 来避免。无论我们是通过第一个循环或预循环调用,使用预循环调用时复杂度会(稍微)更高。
This is similar to the previous but works forward through the string instead of recursively backwards. Leaves errno with the right value for last failure. If there's a leading slash, there's an extra time through the loop which could have been avoided via one find_first_of() outside the loop or by detecting the leading / and setting pre to 1. The efficiency is the same whether we get set up by a first loop or a pre loop call, and the complexity would be (slightly) higher when using the pre-loop call.
你说的是“C++”,但这里的每个人似乎都在想“Bash shell”。
查看 gnu
mkdir
的源代码; 然后你可以看到如何用C++实现shell命令。You said "C++" but everyone here seems to be thinking "Bash shell."
Check out the source code to gnu
mkdir
; then you can see how to implement the shell commands in C++.所以我今天需要
mkdirp()
,并且发现此页面上的解决方案过于复杂。因此,我写了一个相当短的片段,可以很容易地复制给其他人
偶然发现这个线程,想知道为什么我们需要这么多行代码。
mkdirp.h
mkdirp.cpp
如果您不喜欢 const 转换和临时修改字符串,只需执行
strdup()
和然后释放()
它。So I need
mkdirp()
today, and found the solutions on this page overly complicated.Hence I wrote a fairly short snippet, that easily be copied in for others who
stumble upon this thread an wonder why we need so many lines of code.
mkdirp.h
mkdirp.cpp
If you don't like const casting and temporarily modifying the string, just do a
strdup()
andfree()
it afterwards.由于这篇文章在“创建目录树”方面在 Google 中排名很高,因此我将发布一个适用于 Windows 的答案 - 这将使用为 UNICODE 或 MBCS 编译的 Win32 API 来工作。 这是从上面 Mark 的代码移植的。
由于我们使用的是 Windows,因此目录分隔符是反斜杠,而不是正斜杠。 如果您希望使用正斜杠,请将
'\\'
更改为'/'
它将适用于:
并且
(即:不需要尾部斜杠,因此您不必检查它。)
在说“只需在 Windows 中使用 SHCreateDirectoryEx()”之前,请注意 SHCreateDirectoryEx()< /strong> 已弃用,并且可能随时从未来版本的 Windows 中删除。
Since this post is ranking high in Google for "Create Directory Tree", I am going to post an answer that will work for Windows — this will work using Win32 API compiled for UNICODE or MBCS. This is ported from Mark's code above.
Since this is Windows we are working with, directory separators are BACK-slashes, not forward slashes. If you would rather have forward slashes, change
'\\'
to'/'
It will work with:
and
(i.e.: does not need trailing slash, so you don't have to check for it.)
Before saying "Just use SHCreateDirectoryEx() in Windows", note that SHCreateDirectoryEx() is deprecated and could be removed at any time from future versions of Windows.
我知道这是一个老问题,但它在谷歌搜索结果中显示得很高,而且这里提供的答案并不是真正用 C++ 编写的,或者有点太复杂了。
请注意,在我的示例中,createDirTree() 非常简单,因为无论如何,所有繁重的工作(错误检查、路径验证)都需要由 createDir() 完成。 如果目录已经存在,createDir() 也应该返回 true,否则整个过程将无法工作。
下面是我在 C++ 中的做法:
当然 createDir() 函数将是特定于系统的,并且其他答案中已经有足够的示例如何为 Linux 编写它,所以我决定跳过它。
I know it's an old question but it shows up high on google search results and the answers provided here are not really in C++ or are a bit too complicated.
Please note that in my example createDirTree() is very simple because all the heavy lifting (error checking, path validation) needs to be done by createDir() anyway. Also createDir() should return true if directory already exists or the whole thing won't work.
Here's how I would do that in C++:
Of course createDir() function will be system-specific and there are already enough examples in other answers how to write it for linux, so I decided to skip it.
这里描述了很多方法,但大多数方法都需要将路径硬编码到代码中。
对于这个问题有一个简单的解决方案,使用 QDir 和 QFileInfo(Qt 框架的两个类)。 由于您已经在 Linux 环境中,因此使用 Qt 应该很容易。
确保您对该路径具有写入权限。
So many approaches has been described here but most of them need hard coding of your path into your code.
There is an easy solution for that problem, using QDir and QFileInfo, two classes of Qt framework. Since your already in Linux environment it should be easy to use Qt.
Make sure you have write access to that Path.
如果 dir 不存在,则创建它:
If dir does not exist, create it:
下面是 C/C++ 递归函数,它利用
dirname()
自下而上遍历目录树。 一旦找到现有的祖先,它就会停止。Here's C/C++ recursive function that makes use of
dirname()
to traverse bottom-up the directory tree. It will stop as soon as it finds an existing ancestor.如果您还没有 C++17 并且正在寻找与平台无关的解决方案,请使用 ghc::filesystem。 标头代码与 C++17 兼容(实际上是向后移植),并且以后很容易迁移。
If you don't have C++17 yet and look for a platform agnostic solution, use ghc::filesystem. The header-ony code is compatible to C++17 (in fact a backport) and easy to migrate later on.
其他人给了你正确的答案,但我想我会演示你可以做的另一件巧妙的事情:
将创建以下路径:
大括号允许您在层次结构的同一级别上一次创建多个目录,而
-p
选项表示“根据需要创建父目录”。The others got you the right answer, but I thought I'd demonstrate another neat thing you can do:
Will create the following paths:
The braces allow you to create multiple directories at once on the same level of the hierarchy, whereas the
-p
option means "create parent directories as needed".