PDA

View Full Version : سوال: حذف یک فولدر در c



titans
شنبه 09 اسفند 1399, 18:57 عصر
با سلام!
دوستان من میخوام کد بنویسم که وقتی کاربر اونو باز میکنه یک فولدر در مکان خاص پاک بشه خواهشا دوستانی که بلدن راهنمایی کنند!

sd702004
یک شنبه 10 اسفند 1399, 10:34 صبح
سلام. روش این کار به سیستم عامل بستگی داره. اینجا برای لینوکس و ویندوز توضیح داده: (توجه داشته باشید که یوزری که برنامه شما رو اجرا میکنه باید دسترسی برای حذف اون فولدر خاص و محتویات داخلش رو داشته باشه)

https://stackoverflow.com/questions/2256945/removing-a-non-empty-directory-programmatically-in-c-or-c

titans
یک شنبه 10 اسفند 1399, 11:33 صبح
با سلام!
مثلا در ویندوز، به محض اینکه فایل باز شد یک پوشه رو پاک کنه!

sd702004
یک شنبه 10 اسفند 1399, 12:39 عصر
در ویندوز تابعی به نام RemoveDirectory با دو عنوان RemoveDirectoryA و RemoveDirectoryW (اولی فقط ANSI و دومی Unicode) وجود داره که یک فولدر خالی رو حذف میکنه. بنابراین برای این که یک فولدر رو حذف کنیم ابتدا لازمه محتویات داخلش رو حذف کنیم که محتویات داخل اون ممکنه فایل و یا فولدرهای دارای فایل باشه. بنابراین اولین کاری که باید انجام بشه باز کردن فایلهای داخل یک فولدر با دستور FindFirstFile و سپس رفتن به داخل فایلها و فولدرهای بعدی با دستور FindNextFile هست. هر جا به فایلی رسیدیم با دستور DeleteFile اون فایل رو حذف میکنید و هر جا به فولدر رسیدین ابتدا وارد اون فولدر میشید و فایلهاش رو حذف میکنید و سپس با دستور RemoveDirectory اون فولدر رو حذف میکنید. یک روش پیاده سازی ساده هم اینه که بصورت recursive کدتون رو بنویسید.
این توابع در هدر Windows.h قرار داره. روش های دیگری هم در API ویندوز برای حذف یک فولدر امکان پذیره.

titans
دوشنبه 11 اسفند 1399, 15:09 عصر
با سلام!
میشه کد حذفش رو بنویسید که چجوری وارد پوشه ای بشم و محتویاتش رو پاک کنم!

sd702004
دوشنبه 11 اسفند 1399, 19:06 عصر
این کد تمام فایلها و فولدرها رو به همون ترتیبی که باید حذف بشه نمایش میده و چیزی رو حذف نمیکنه. یه بررسی بکنید کلیاتش دست تون میاد. برای حذف هم کافیه هر جا فولدر بود از تابع RemoveDirectoryW و هر جا فایل داشتین از تابع DeleteFileW استفاده کنید. علت استفاده از wide char هم به این خاطر بود که اگه فایل/فولدر فارسی هم داشتین توی حذفش مشکلی پیش نیاد. (یک روش تک خطی هم وجود داره و اون استفاده از دستورات cmd داخل تابع system هست ولی خب روش اصولیش همین روش زیره)

در این مثال محتویات داخل فولدر فرضی test واقع در درایو d بصورت recursive نمایش داده میشه (دقت کنید که در انتهای استرینگ نباید کارکتر اسلش یا بک اسلش وجود داشته باشه)
#include <Windows.h>
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

void delete_folder(const wchar_t *path);

int main(void){
delete_folder(L"d:/test");
return 0;
}

void delete_folder(const wchar_t *path){
int sz = wcslen(path) + 3;
wchar_t *search_path = (wchar_t *)malloc(sz * sizeof(wchar_t));
swprintf(search_path, sz, L"%S/*", path);

WIN32_FIND_DATAW find_data;
HANDLE handle = FindFirstFileW(search_path, &find_data);
free(search_path);

if (handle == INVALID_HANDLE_VALUE){
fprintf(stderr, "finding %S failed\n", path);
return;
}

do {
if ( wcscmp(find_data.cFileName, L".") == 0 || wcscmp(find_data.cFileName, L"..") == 0 )
continue;

if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
int sz = wcslen(path) + wcslen(find_data.cFileName) + 2;
wchar_t *subfolder_path = (wchar_t *)malloc(sz * sizeof(wchar_t));
swprintf(subfolder_path, sz, L"%S/%S", path, find_data.cFileName);
delete_folder(subfolder_path);
free(subfolder_path);
} else {
wprintf(L"file: %S/%S\n", path, find_data.cFileName);
}

} while (FindNextFileW(handle, &find_data));

wprintf(L"folder: %S\n", path);
FindClose(handle);
}

titans
سه شنبه 12 اسفند 1399, 19:56 عصر
با سلام!
الان کد بالا هر چیزی که توی اون پوشه است را پاک میکنه!

sd702004
سه شنبه 12 اسفند 1399, 21:30 عصر
خیر. همون طور که گفتم این کد فایل و فولدرها رو به ترتیبی که باید پاک بشن بر اساس مسیر کامل شون لیست میکنه و صرفا کافیه برای پاک کردن شون از توابع زیر استفاده کنید. هر جا توی کد wprintf وجود داره از توابع زیر برای حذف فولدر یا فایل استفاده کنید.


https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectoryw
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilew

titans
چهارشنبه 13 اسفند 1399, 20:40 عصر
با سلام!
یعنی اون دوجایی که wprintf امده این دستورو بنویسم
BOOL RemoveDirectoryW( LPCWSTR lpPathName);

sd702004
چهارشنبه 13 اسفند 1399, 21:54 عصر
جایی که فولدر دارین از این تابع و جایی که فایل دارین از تابع DeleteFileW باید استفاده بشه. ورودی این دو تابع هم یه استریگ wide ـه. کد رو تغییر دادم. این کد فولدر فرضی test واقع در درایو d رو به طور کامل پاک میکنه (مشروط بر اینکه یوزری که این فایل رو اجرا میکنه دسترسی برای حذف فولدر توی اون مسیر خاص رو داشته باشه).

#include <Windows.h>
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

void delete_folder(const wchar_t *path);

int main(void){
delete_folder(L"D:/test");
return 0;
}

void delete_folder(const wchar_t *path){
int sz = wcslen(path) + 3;
wchar_t *search_path = (wchar_t *)malloc(sz * sizeof(wchar_t));
swprintf(search_path, sz, L"%S/*", path);

WIN32_FIND_DATAW find_data;
HANDLE handle = FindFirstFileW(search_path, &find_data);
free(search_path);

if (handle == INVALID_HANDLE_VALUE){
fprintf(stderr, "finding %S failed\n", path);
return;
}

do {
if ( wcscmp(find_data.cFileName, L".") == 0 || wcscmp(find_data.cFileName, L"..") == 0 )
continue;

int sz = wcslen(path) + wcslen(find_data.cFileName) + 2;
wchar_t *filefolder_path = (wchar_t *)malloc(sz * sizeof(wchar_t));
swprintf(filefolder_path, sz, L"%S/%S", path, find_data.cFileName);

if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
delete_folder(filefolder_path);
} else {
if (!DeleteFileW(filefolder_path))
fprintf(stderr, "could not delete %S\n", filefolder_path);
}

free(filefolder_path);

} while (FindNextFileW(handle, &find_data));

if (!RemoveDirectoryW(path))
fprintf(stderr, "could not delete %S\n", path);

FindClose(handle);
}

titans
پنج شنبه 14 اسفند 1399, 13:08 عصر
با سلام!
این کد در درایو c هم جواب میده؟

sd702004
پنج شنبه 14 اسفند 1399, 15:29 عصر
با سلام. اگه فولدرهایی که نیاز به دسترسی خاص دارن (مثل program files و ...) منظورتونه امکان پذیر نیست چون خود سیستم عامل اجازه نمیده و تنها در صورتی که برنامه بصورت administrator اجرا شده باشه این کار امکان پذیره

titans
جمعه 15 اسفند 1399, 20:25 عصر
با سلام!
میشه کاری کرد که فقط رو
administrator اجرا بشه؟

sd702004
شنبه 16 اسفند 1399, 00:51 صبح
اگه منظورتون اینه که فایل بصورت پیشفرض در حالت ادمینستریتور اجرا بشه، در صورتی که به سیستمی که مد نظرتون هست دسترسی دارید بله میشه. کافیه توی سیستم مد نظر روی فایل exe کلیک راست کنید و حالتش رو run as administrator بذارید در غیر این صورت سیستم عامل دسترسی برای چنین کاری رو نمیده چرا که امنیت سیستم به خطر میفته.

امیدوارم از حرفم برداشت اشتباه نشه اما با این روش به هیچ وجه، حذف فایلهای مهم سیستم عامل امکان پذیر نیست.

titans
شنبه 16 اسفند 1399, 19:44 عصر
با سلام!
خود برنامه های یه فایل دارن با نام 000.bat اون اگه اجرا بشه برنامه پاک میشه؟

sd702004
یک شنبه 17 اسفند 1399, 01:00 صبح
باید دید محتوای اون فایل bat چیه. اگه دستورات حذف داخلش نوشته شده بله این کار قابل انجامه (مشروط بر اینکه یوزر دسترسی برای حذف داشته باشه). در حالت کلی برای حذف فایل و فولدر چه از طریق یک فایل exe چه از طریق batch file، یوزری که فایل رو اجرا میکنه باید دسترسی برای حذف اون فولدر رو داشته باشه در غیر این صورت این کار ممکن نیست و سیستم عامل اجازه حذف نمیده