PDA

View Full Version : سوال: حذف تمام عکس های یک پوشه در c



titans
شنبه 23 مرداد 1400, 14:29 عصر
با سلام!
من میخوام در c یک برنامه نویسم که وقتی اجرا میشه همه عکس های یک پوشه رو پاک کنه البته باید بگم که مثلا در پوشه f1 یک پوشه f2 هم قرار داره و به همین ترتیب به پایین(پوشه های درون پوشه های دیگه) میخوام برنامه همه عکس های این پوشه رو پاک کنه یعنی برود درون پوشه های بگرده اگه عکسی هست پاک کنه ممنون میشم کمک کنید!

sd702004
شنبه 23 مرداد 1400, 20:40 عصر
سلام. توی این تاپیک نحوه حذف یک فولدر توضیح داده شده. به صورت مشابه میتونید با کمی تغییر از همین روش برای حذف تصاویر استفاده کنید:

https://barnamenevis.org/showthread.php?564736-%D8%AD%D8%B0%D9%81-%DB%8C%DA%A9-%D9%81%D9%88%D9%84%D8%AF%D8%B1-%D8%AF%D8%B1-c

titans
یک شنبه 24 مرداد 1400, 15:14 عصر
سلام من اون کد رو تست کردم اما همه ی فایل هارو پاک میکنه ولی من میخوام فقط عکس هارو پاک کنه!

sd702004
یک شنبه 24 مرداد 1400, 15:38 عصر
همون طور که گفتم این کد برای حذف یک فولدر نوشته شده و برای تصویر باید تغییرش بدید و بگید که فایل هایی که پسوند تصویر دارن (مثل jpg، png و ...) فقط حذف بشه. برای کدی که شما میخواین فقط باید از دستور DeleteFileW استفاده بشه و نه RemoveDirectoryW. در متغیر cFileName هم اسم فایل ذخیره میشه که میتونید پسوند رو از این طریق کنترل کنید.

titans
یک شنبه 24 مرداد 1400, 16:02 عصر
من در قسمت cFileName, L"." رو به cFileName, L".mp4" تبدیل کردم اما باز همه ی فایل هارو پاک میکنه!

sd702004
یک شنبه 24 مرداد 1400, 16:36 عصر
توی C با چنین روشی نمیشه استرینگ ها رو مقایسه کرد. برای بررسی این که پسوند فایل چیه از روشی که اینجا توضیح داده شده باید استفاده کنید:

https://stackoverflow.com/questions/744766/how-to-compare-ends-of-strings-in-c
این تغییرات رو هم انجام بدین:
char به wchar_t
strlen به wcslen
strncmp به wcsncmp

titans
یک شنبه 24 مرداد 1400, 19:59 عصر
من این کد رو اضافه کردم
int EndsWith(const wchar_t *str, const wchar_t *suffix){
if (!str || !suffix)
return 0;
size_t lenstr = wcslen(str);
size_t lensuffix = wcslen(suffix);
if (lensuffix > lenstr)
return 0;
return wcsncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}


int EndsWithFoo(const wchar_t *str) { return EndsWith(str, ".foo"); }

و این ارورو داد

main.cpp|65|error: cannot convert 'const char*' to 'const wchar_t*'|

sd702004
یک شنبه 24 مرداد 1400, 20:17 عصر
کلمه "foo" یک استرینگ معمولیه و از نوع wide نیست و این ارور به این دلیله. حالا این به کنار، این قسمت صرفا یک مثاله و اصلا نباید توی کد تون باشه. این خط رو کامل حذف کنید:
int EndsWithFoo(const wchar_t *str) { return EndsWith(str, ".foo"); }


برای چک کردن پسوند (مثلا jpg) به این صورت عمل کنید:
if ( EndsWith(find_data.cFileName, L".jpg") ){
// delete file
}

titans
دوشنبه 25 مرداد 1400, 15:38 عصر
من الان این کد رو دقیقا کجا قرار بدم؟(هر جا قرار دارم ارور داد!)

sd702004
دوشنبه 25 مرداد 1400, 17:06 عصر
ساده ترین کار اینه که بدنه تابع رو قبل از main بذارید. قبل از دستور حذف هم با این تابع پسوند رو چک کنید که مال عکس باشه همین. اگه باز هم کامپایل نمیشه لطفا کل کد رو اینجا قرار بدین تا بشه فهمید مشکل از کجاست.

titans
سه شنبه 26 مرداد 1400, 11:59 صبح
باز کامپایل نشد اینم کدش
#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){
if ( EndsWith(find_data.cFileName, L".jpg") ){
// delete file
delete_folder(filefolder_path);
}


} else {
if (!DeleteFileW(filefolder_path))
fprintf(stderr, "could not deleteq %S\n", filefolder_path);
}


free(filefolder_path);


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


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


FindClose(handle);
}


اینم ارورش
main.cpp|36|error: 'EndsWith' was not declared in this scope|

sd702004
سه شنبه 26 مرداد 1400, 13:32 عصر
شما از تابع EndsWith استفاده کردین ولی هیچ جا تعریفش رو نذاشتین. تابع هم در جای اشتباهی گذاشته شده. در صورت برقرار بودن شرط باید دستور DeleteFileW اجرا بشه نه فراخوانی مجدد تابع. از RemoveDirectoryW هم نباید استفاده کنید چون فولدر که قرار نیست پاک بشه.

titans
چهارشنبه 27 مرداد 1400, 17:10 عصر
با اون کد بالا هیچ فولدری پاک نمیشه!
راجب تابع endswith هم باید بگم که من هنوز نمیدونم کجا کد فایل رو پاک میکنه که دستور شرط رو انجام بدم!

sd702004
چهارشنبه 27 مرداد 1400, 17:47 عصر
حذف فایل همون طور که از اسم تابع هم مشخصه توسط DeleteFileW انجام میشه. البته این مورد رو جلوتر تو همین تاپیک گفته بودم خدمت تون (پست چهارم):
"برای کدی که شما میخواین فقط باید از دستور DeleteFileW استفاده بشه و نه RemoveDirectoryW"

titans
پنج شنبه 28 مرداد 1400, 14:54 عصر
در کدی که قبلا فرستادم(در پست11) دستور deletefilew وجود ندارد ولی باز فایل هارو پاک میکنه!

sd702004
پنج شنبه 28 مرداد 1400, 17:17 عصر
خیر این طور نیست. در کد پست 11 در خط 50 از این تابع استفاده شده.

titans
جمعه 29 مرداد 1400, 14:17 عصر
من الان دستور چک برای حذف فایل که در خط 50 انجام میشه رو اینطور نوشتم
if ( EndsWith(find_data.cFileName, L".jpg") ){ // delete file
if (!DeleteFileW(filefolder_path))
fprintf(stderr, "could not deleteq %S\n", filefolder_path);
}
ولی باز ارور main.cpp|51|error: 'EndsWith' was not declared in this scope| رو میده

sd702004
جمعه 29 مرداد 1400, 16:20 عصر
دلیلش اینه که تعریف تابع EndsWith (خط 1 تا 9 پست شماره 7) رو در کدتون قرار ندادین

titans
یک شنبه 31 مرداد 1400, 17:28 عصر
چطور تایع EndsWith در کدم تعریف کنم؟

sd702004
یک شنبه 31 مرداد 1400, 18:19 عصر
به همون صورتی که تابع delete_folder تعریف شده. کافیه بدنه تابع رو در انتهای کد تون پیست کنید و قبل از تابع main هم این خط رو اضافه کنید:
int EndsWith(const wchar_t *str, const wchar_t *suffix);

titans
دوشنبه 01 شهریور 1400, 19:21 عصر
باز این ارورو داد
main.o:main.cpp|| undefined reference to `EndsWith(wchar_t const*, wchar_t const*)'|

sd702004
دوشنبه 01 شهریور 1400, 20:40 عصر
کد رو کامل بذارید چون احتمالا یک چیزی رو جا انداختید.

titans
دوشنبه 01 شهریور 1400, 21:21 عصر
بفرمایید
#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;
}




int EndsWith(const wchar_t *str, const wchar_t *suffix);
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 file
delete_folder(filefolder_path);






} else {
if ( EndsWith(find_data.cFileName, L".jpg") ){
// delete file
if (!DeleteFileW(filefolder_path))
fprintf(stderr, "could not deleteq %S\n", filefolder_path);
}


}




free(filefolder_path);




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




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




FindClose(handle);
}

sd702004
دوشنبه 01 شهریور 1400, 22:13 عصر
خب علتش اینه که تعریف تابع EndsWith رو در هیچ جای کد تون قرار ندادین. دستور زیر رو به انتهای کد اضافه کنید (خارج از بلاک توابع دیگه):

int EndsWith(const wchar_t *str, const wchar_t *suffix){
if (!str || !suffix)
return 0;
size_t lenstr = wcslen(str);
size_t lensuffix = wcslen(suffix);
if (lensuffix > lenstr)
return 0;
return wcsncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}



خط 21 هم بهتره قبل از تابع main قرار بگیره. کدهای خط 93 و 94 رو هم حذف کنید. تابع RemoveDirectoryW این جا کاربردی نداره چون هدف صرفا حذف فایله نه دایرکتوری.

titans
سه شنبه 02 شهریور 1400, 01:29 صبح
مننون اروری نداد حالا اگر بخوایم مثل چند پسوند رو پک کنه بهتره چند تا دستور if بنویسیم یا میشه گفت چندتا رو خوش چک کنه؟

sd702004
سه شنبه 02 شهریور 1400, 10:18 صبح
خواهش میکنم. نه نیازی به چند تا if نیست. کافیه یه آرایه تعریف کنید و پسوندهای مورد نظر تون رو داخلش قرار بدین. بعنوان مثال میشه داخل بدنه تابع delete_folder در ابتدا این آرایه رو تعریف کرد:
static const wchar_t *extensions[] = { L".jpg", L".png", L".tif", L".gif", L".bmp" };
static const int ex_size = (int)sizeof(extensions)/sizeof(extensions[0]);

این قسمت از کد رو هم حذف کنید کنید:
if ( EndsWith(find_data.cFileName, L".jpg") ){
// delete file
if (!DeleteFileW(filefolder_path))
fprintf(stderr, "could not deleteq %S\n", filefolder_path);
}


و به جاش با این کد جایگزین کنید:
for (int i=0; i<ex_size; ++i){
if ( EndsWith(find_data.cFileName, extensions[i]) ){
if (!DeleteFileW(filefolder_path))
fprintf(stderr, "could not delete %S\n", filefolder_path);

break;
}
}

titans
سه شنبه 02 شهریور 1400, 14:06 عصر
این کد فولدر های فارسی هم میگرده و همینطور هیدن شده و همینطور فایل های فارسی؟

sd702004
سه شنبه 02 شهریور 1400, 14:58 عصر
بله. به دلیل استفاده از wchar_t به جای char مشکلی از بابت فایل و فولدرهای فارسی وجود نداره. در خصوص فایل های hidden خودم تست نکردم ولی فکر نمیکنم مشکلی وجود داشته باشه.

titans
سه شنبه 02 شهریور 1400, 19:53 عصر
اگه بخوایم به جای پاک عملیات کات رو انجام بده باید چکار کرد؟

sd702004
سه شنبه 02 شهریور 1400, 20:39 عصر
با این تابع میتونید فایل ها رو move کنید:

https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefilew