Рекурсивный mkdir () системный вызов на Unix

После чтения mkdir (2) страница справочника для системного вызова Unix с тем именем, кажется, что вызов не создает промежуточные каталоги в пути, только последний каталог в пути. Есть ли какой-либо путь (или другая функция) для создания всех каталогов в пути, не обращаясь к ручному парсингу моей строки каталога и индивидуально созданию каждого каталога?

65
задан Carl Norum 25 February 2010 в 17:48
поделиться

4 ответа

К сожалению, нет системного вызова, чтобы сделать это для вас. Я предполагаю, что это потому, что нет способа иметь действительно четко определенную семантику для того, что должно происходить в случаях ошибок. Должен ли он оставить каталоги, которые уже были созданы? Удалять их? Что делать, если удаление не удалось? И так далее...

Однако, довольно легко создать свой собственный, и быстрый поиск в гугле по 'recursive mkdir' выявил ряд решений. Вот одно из них, которое было на первом месте:

http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html

static void _mkdir(const char *dir) {
        char tmp[256];
        char *p = NULL;
        size_t len;

        snprintf(tmp, sizeof(tmp),"%s",dir);
        len = strlen(tmp);
        if(tmp[len - 1] == '/')
                tmp[len - 1] = 0;
        for(p = tmp + 1; *p; p++)
                if(*p == '/') {
                        *p = 0;
                        mkdir(tmp, S_IRWXU);
                        *p = '/';
                }
        mkdir(tmp, S_IRWXU);
}
86
ответ дан 24 November 2019 в 15:11
поделиться

Посмотрите исходный код bash здесь, и особенно посмотрите в examples/loadables/mkdir.c, особенно строки 136-210. Если вы не хотите этого делать, вот некоторые исходные тексты, посвященные этому (взятые прямо из tar.gz, на который я дал ссылку):

/* Make all the directories leading up to PATH, then create PATH.  Note that
   this changes the process's umask; make sure that all paths leading to a
   return reset it to ORIGINAL_UMASK */

static int
make_path (path, nmode, parent_mode)
     char *path;
     int nmode, parent_mode;
{
  int oumask;
  struct stat sb;
  char *p, *npath;

  if (stat (path, &sb) == 0)
  {
      if (S_ISDIR (sb.st_mode) == 0)
      {
          builtin_error ("`%s': file exists but is not a directory", path);
          return 1;
      }

      if (chmod (path, nmode))
      {
          builtin_error ("%s: %s", path, strerror (errno));
          return 1;
      }

      return 0;
  }

  oumask = umask (0);
  npath = savestring (path);    /* So we can write to it. */

  /* Check whether or not we need to do anything with intermediate dirs. */

  /* Skip leading slashes. */
  p = npath;
  while (*p == '/')
    p++;

  while (p = strchr (p, '/'))
  {
      *p = '\0';
      if (stat (npath, &sb) != 0)
      {
          if (mkdir (npath, parent_mode))
          {
              builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
              umask (original_umask);
              free (npath);
              return 1;
          }
      }
      else if (S_ISDIR (sb.st_mode) == 0)
      {
          builtin_error ("`%s': file exists but is not a directory", npath);
          umask (original_umask);
          free (npath);
          return 1;
      }

      *p++ = '/';   /* restore slash */
      while (*p == '/')
          p++;
  }

  /* Create the final directory component. */
  if (stat (npath, &sb) && mkdir (npath, nmode))
  {
      builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
      umask (original_umask);
      free (npath);
      return 1;
  }

  umask (original_umask);
  free (npath);
  return 0;
}

Вероятно, вы можете обойтись менее общей реализацией.

9
ответ дан 24 November 2019 в 15:11
поделиться

По-видимому, нет, мои два предложения:

char dirpath[80] = "/path/to/some/directory";
sprintf(mkcmd, "mkdir -p %s", dirpath);
system(mkcmd);

Или, если вы не хотите использовать system () , попробуйте посмотреть исходный код coreutils mkdir и посмотрите, как они реализовали параметр -p .

7
ответ дан 24 November 2019 в 15:11
поделиться

Два других ответа даны для mkdir (1) , а не для mkdir (2) , как вы просите, но вы можете посмотреть исходный код для этой программы и посмотрите, как она реализует параметры -p , которые повторно вызывают mkdir (2) по мере необходимости.

0
ответ дан 24 November 2019 в 15:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: