Удаление не пустого каталога программно в C или C++

Как удалить не пустой каталог в C или C++? Есть ли какая-либо функция? rmdir только удаляет пустой каталог. Позвольте, не пользуясь никакой внешней библиотекой.

Также скажите мне, как удалить файл в C или C++?

48
задан Donald Duck 6 March 2017 в 16:41
поделиться

4 ответа

Вы хотите написать функцию (рекурсивная функция проще, но может легко не хватить места в стеке в глубоких каталогах), которая будет перечислять дочерние элементы каталог. Если вы найдете дочерний элемент, который является каталогом, вы перейдете к нему. В противном случае вы удалите файлы внутри. Когда вы закончите, каталог станет пустым, и вы можете удалить его с помощью системного вызова.

Для перечисления каталогов в Unix вы можете использовать opendir , readdir и closedir . Чтобы удалить, используйте rmdir () в пустом каталоге (т.е. в конце вашей функции после удаления дочерних элементов) и unlink () в файле. Обратите внимание, что во многих системах член d_type в struct dirent не поддерживается; на этих платформах вам придется использовать stat () и S_ISDIR (stat.st_mode) , чтобы определить, является ли данный путь каталогом.

В Windows вы будете использовать FindFirstFile () / FindNextFile () для перечисления, RemoveDirectory () для пустых каталогов и DeleteFile ( ) для удаления файлов.

Вот пример, который может работать в Unix (полностью не протестирован):

int remove_directory(const char *path)
{
   DIR *d = opendir(path);
   size_t path_len = strlen(path);
   int r = -1;

   if (d)
   {
      struct dirent *p;

      r = 0;

      while (!r && (p=readdir(d)))
      {
          int r2 = -1;
          char *buf;
          size_t len;

          /* Skip the names "." and ".." as we don't want to recurse on them. */
          if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
          {
             continue;
          }

          len = path_len + strlen(p->d_name) + 2; 
          buf = malloc(len);

          if (buf)
          {
             struct stat statbuf;

             snprintf(buf, len, "%s/%s", path, p->d_name);

             if (!stat(buf, &statbuf))
             {
                if (S_ISDIR(statbuf.st_mode))
                {
                   r2 = remove_directory(buf);
                }
                else
                {
                   r2 = unlink(buf);
                }
             }

             free(buf);
          }

          r = r2;
      }

      closedir(d);
   }

   if (!r)
   {
      r = rmdir(path);
   }

   return r;
}
29
ответ дан 26 November 2019 в 18:55
поделиться

unlink удалит файл.

remove также удалит файл, но более переносимый.

Вы можете попробовать system ("rm -r ./path"), если вы работаете в Linux, иначе есть также функция рекурсивного удаления Windows API.

0
ответ дан 26 November 2019 в 18:55
поделиться

Как правило, большинство людей хотят, чтобы youtube видео ID. Чтобы просто соответствовать этому, используйте следующий regex.

var matches = _videoUrl.match(/watch\?v=([a-zA-Z0-9\-_]+)/);
if (matches)
{
    alert('valid');
}

Естественно, регекс можно расширить, включив в него весь URL-адрес youtube, но если вам нужен только идентификатор, это самый надежный способ, который я нашел.

-121--3095695-

Код ошибки Microsft SQL Server для взаимоблокировки является 1205, поэтому необходимо обработать SqlException и проверить его. Таким образом, например, если для всех других типов SqlException необходимо, чтобы пузырь имел исключение вверх:

catch (SqlException ex)
{
    if (ex.Number == 1205)
    {
        // Deadlock 
    }
    else
        throw;
}

Или, используя фильтрацию исключений, доступную в C # 6

catch (SqlException ex) when (ex.Number == 1205)
{
    // Deadlock 
}

Удобная вещь, чтобы найти фактический код ошибки SQL для данного сообщения, является поиск в sys.messages в SQL Server.

например.

SELECT * FROM sys.messages WHERE text LIKE '%deadlock%' AND language_id=1033

Альтернативный способ обработки взаимоблокировок (от SQL Server 2005 и выше), это сделать в рамках хранимой процедуры с помощью поддержки TRY... CATCH:

BEGIN TRY
    -- some sql statements
END TRY
BEGIN CATCH
    IF (ERROR_NUMBER() = 1205)
        -- is a deadlock
    ELSE
        -- is not a deadlock
END CATCH

Есть полный пример здесь в MSDN того, как реализовать логику повторных попыток взаимоблокировки чисто в SQL.

-121--795116-

Для чтения записей каталога можно использовать opendir и readdir , а для их удаления - unlink .

1
ответ дан 26 November 2019 в 18:55
поделиться

Самый простой способ сделать это - использовать функцию remove_all библиотеки Boost.Filesystem. Кроме того, полученный код будет переносимым.

Если вы хотите написать что-то особенное для Unix (rmdir) или для Windows (RemoveDirectory), вам придется написать функцию, которая рекурсивно удаляет субфайлы и подпапки.

РЕДАКТИРОВАТЬ

Похоже, этот вопрос уже задавали , на самом деле кто-то уже рекомендовал remove_all от Boost. Поэтому, пожалуйста, не голосуйте за мой ответ.

14
ответ дан 26 November 2019 в 18:55
поделиться