C - Unlink/Remove производит ошибку для имен файлов с пробелами
Я пытаюсь сделать функцию в C, чтобы стереть все содержимое временной папки и стереть папку.
Хотя я уже успешно создал код для циклического перемещения по файлам и удаления папки (это довольно просто), у меня возникают проблемы при удалении файлов с помощью unlink.
Вот код, который я использую:
int delete_folder(char *foldername) {
DIR *dp;
struct dirent *ep;
dp=opendir(foldername);
if (dp!=NULL) {
readdir(dp); readdir(dp);
while (ep=readdir(dp)) {
char* cell = concatenate(concatenate(foldername, "\\"), "Bayesian Estimation.xlsx");//ep->d_name);
printf("%s\n", cell);
remove(cell);
printf("%s\n", strerror(errno));
}
closedir(dp);
}
if (!rmdir(foldername)) {return(0);} else {return(-1);}
}
Код, который я написал, полностью функционален для всех файлов, кроме тех, которые содержат пробелы в имени файла. После некоторого тестирования я могу гарантировать, что функции отмены связи удаляют все файлы в папке (даже те, которые содержат специальные символы в имени файла), но не работают, если имя файла содержит пробел (однако, для этого же файла, если я удаляю пробел (s)), эта функция снова работает).
Кто-нибудь еще сталкивался с этой проблемой? И, что более важно, это может быть решено / обойдено?
(Проблема остается, даже если я введу последовательности выхода из космоса напрямую)
Ошибка, представленная unlink: "Нет такого файла или каталога" (ENOENT). Имейте в виду, что файл действительно находится в указанном месте (что можно проверить с помощью кода, выводящего правильное имя файла в ячейке переменной), и эта ошибка также возникает, если я использую функцию remove вместо unlink.
PS: функция concatenate - это моя собственная функция, которая выводит конкатенацию двух входных строк.
Изменить: код был написан в Codeblocks, в Windows.
Вот код для функции сцепления:
char* concatenate(char *str1, char *str2) {
int a1 = strlen(str1), a2 = strlen(str2); char* str3[a1+a2+1];
snprintf(str3, a1+a2+2, "%s%s", str1, str2);
return(str3);
}
Несмотря на то, что вы правы, говоря, что это возможная (и простая) утечка памяти, входы и выходы функций генерируются кодом и предназначены только для личного использования, и, следовательно, нет серьезных оснований для беспокойства по этому поводу (нет реальной необходимости защищать от ошибок). код.)
2 ответа
Большое спасибо за ваш вклад, после того как я просмотрел ваши комментарии и сам провел несколько экспериментов, я понял, что удаление / отмена связи не работает, потому что имя файла только временно сохранялось в переменной ячейке (оно было там достаточно долго, чтобы правильно напечатано на консоли, отсюда и мое замешательство). После надлежащего сохранения моего имени файла перед использованием, моя проблема была полностью решена.
Вот код (я уже проверил его с именами файлов настолько сложными, насколько я мог их сделать):
int delete_folder(char* foldername) {
DIR *dp;
struct dirent *ep;
dp=opendir(foldername);
if (dp!=NULL) {
readdir(dp); readdir(dp);
while (ep=readdir(dp)) {
char cell[strlen(foldername)+1+strlen(ep->d_name)+1];
strcpy(cell, concatenate(concatenate(foldername, "\\"), ep->d_name));
unlink(cell);
printf("File \"%s\": %s\n", ep->d_name, strerror(errno));
}
closedir(dp);
}
if (!rmdir(foldername)) {return(0);} else {return(-1);}
}
Я понимаю, что это была своего рода ошибка новичка, из-за того, что я немного потренировался в программировании на C, так что... Большое спасибо за вашу помощь!
Вы говорите, "используя unlink()
"но код использует remove()
, На какой ты платформе? Есть ли опасность, что ваша платформа реализует remove()
запустив внешнюю команду, которая не обрабатывает пробелы в именах файлов должным образом? На большинстве систем это не будет проблемой.
Проблема в том, что вы не проверяете возвращаемое значение из remove()
перед печатью ошибка. Вы должны печатать ошибку только в том случае, если функция указывает, что она вызвала ошибку. Нет функций в наборах библиотек Standard C (или POSIX) errno
в ноль. Также об ошибках следует сообщать по стандартной ошибке; для этого предназначен стандартный поток ошибок.
if (remove(cell) != 0)
fprintf(stderr, "Failed to remove %s (%d: %s)\n", cell, errno, strerror(errno));
else
printf("%s removed OK\n", cell);
Я считаю else
в качестве временной меры, пока вы работаете с кодом.
Выглядит так, как будто вы теряете память, как сито пословиц. Вы фиксируете результат операции двойного сцепления в cell
, но ты никогда не освобождаешь это. Действительно, если оба вложенных вызова выделяют память, то вы получите утечку, даже если добавите free(cell);
в конце цикла (внутри цикла, после второго printf()
тот, который я деконструировал). Если concatenate()
не выделяет новую память каждый раз (он возвращает указатель на статически выделенную память, тогда я думаю, что конкатенация строки с выводом concatenate()
также опасно, вероятно вызывая неопределенное поведение, когда вы копируете строку поверх себя. Вы должны внимательно посмотреть на код для concatenate()
и / или представить его для анализа.