Why does the behavior of mkdir differs on differen

2019-08-03 04:32发布

I was trying to create folders named 1 2 3 4, using the C++ program below. I can successfully achieve that in RHEL. However it created a folder named {1..4} in ubuntu 13.10.

Why does this happen? Thank you for helping me!

    #include <cstdlib>

    int main()
    {
        std::system("mkdir {1..4}");
    }

It's a part of CPP unit test in our product. Yes, it's ugly. But I am afraid very few thing can be done in this situation.

You are right. In RHEL, sh -c 'echo {1..4}' 1 2 3 4

In Ubuntu sh -c 'echo {1..4}' {1..4}

So I use the program below instead. It works! #include

int main()
{
    std::system("bash -c 'mkdir {1..4}'");
}

seems system use sh by default....Thank you for your answer!

标签: c++ system
1条回答
干净又极端
2楼-- · 2019-08-03 04:51

A bit of terminology: Linux has directories in its file systems, not "folders" (folders may appear visually on the desktop, but that is a desktop detail).

You don't need to use system(3) (which is running sh not bash!). And POSIX sh don't know the {1..4} notation, hence the {1..4} string is passed verbatim to /bin/mkdir command (see mkdir(1) ...).

Run

 sh -c 'echo {1..4}'

to test that sh don't understand the {1..4} notation.

(so it is a bug in your old RHEL, where perhaps /bin/sh is a symlink to /bin/bash while on Debian and Ubuntu it is a symlink to the more Posix compliant and faster /bin/dash)

Just use the mkdir(2) syscall and code

#include <cstdlib>
#include <cstdio>
#include <sys/stat.h>
#include <sys/types.h>

int main() {
   for (int i=1; i<=4; i++) {
      char buf[8];
      snprintf(buf, sizeof(buf), "%d", i);
      if (mkdir(buf, 0755))
        { perror("mkdir"); exit(EXIT_FAILURE); };
   }
}

I hope you don't want to create a single directory named 1 2 3 4. It is possible and easy, but it really is poor taste. For your mental safety, use only letters, digits and underscores _ in directory names.

I am using snprintf(3) to convert an int to a character buffer. With C++11 you could use std::to_string and c_str ...

Read Advanced Linux Programming...

Using the mkdir(2) syscall instead of going thru a command invoked by system(3) has several important advantages:

  • it is much faster, you don't need to fork(2) a /bin/sh -c shell like system(3) should do.
  • it uses much less resources, since no additional process is fork-ed, so your program will still run when you have reached your limits (see setrlimit(2) ...)
  • it is more reliable. Should mkdir(2) fail you could (and should) handle the failure nicely. See errno(3) and strerror(3) ....
查看更多
登录 后发表回答