UNIX/Linux ve Windows Sistemlerinde Dizin İçeriğinin Elde Edilmesi Kaan Aslan 11 Haziran 2007 UNIX/Linux ve Windows sistemlerinde dizinlerle dosyalar tamamen aynı biçimde organize edilir. Dizinlerle dosyalar arasındaki tek fark, dosyalara ilişkin bloklarda dosya bilgileri bulunduğu halde dizinlere ilişkin bloklarda dizin girişlerinin bulunmasıdır. Bazı POSIX sistemlerinde dizinler de dosyalar gibi open fonksiyonuyla açılıp içerikleri read fonksiyonuyla okunabilmektedir. Böyle sistemlerde dizinlerin içerisinde bulunan dosya isimleri ve dosyaların düğüm numaraları normal dosya işlemleriyle elde edilebilir. Fakat dizin girişlerinin veri yapıları dosya sistemine göre bazı farklılıklar gösterebiliyorlar. Yani eğer programcı dizin içeriğini bu biçimde elde edecek olsa read fonksiyonu ile her sisteme göre değişik uzunlukta okumalar yapması ve okunanları değişik biçimlerde yorumlaması gerekecektir. Bundan dolayı UNIX türevi sistemlerin büyük çoğunluğu uzunca bir süredir dizin içeriklerinin doğrudan read fonksiyonlarıyla okunabilmesine izin vermiyorlar [1]. Dizin içeriklerinin taşınabilir bir biçimde elde edilmesi için prototipleri <dirent.h> içerisinde bulunan opendir, readdir, seekdir, rewinddir, telldir ve closedir isimli POSIX fonksiyonları kullanılmaktadır. UNIX/Linux sistemlerinde dizin listesini elde etmek için gereken ilk fonksiyon opendir fonksiyonudur. Bu fonksiyona içeriği elde edilecek dizininin yol ifadesi verilir ve fonksiyondan bir handle değeri elde edilir. Bu handle değeri de diğer fonksiyonlara argüman olarak geçirilir. opendir fonksiyonunun prototipini inceleyiniz: DIR *opendir(const char *dirname); Fonksiyon içeriği elde edilecek dizinin yol ifadesini parametre olarak alır. Başarı durumunda DIR isimli bir yapı adresine geri döner. POSIX standartlarında DIR isminin bir tür belirttiği söylenmiştir fakat bunun nasıl bir tür olduğu hakkında bir belirlemede bulunulmamıştır. Programcı elde ettiği bu DIR türünden adresi yalnızca diğer fonksiyonlara parametre olarak geçirmek için kullanır. Yani programcı DIR yapısının içeriğini bilmek zorunda değildir. opendir fonksiyonu başarısız olabilir. Başarısızlık durumunda NULL adresle geri döner. Başarısızlığın tipik nedenleri ve errno değişkeninin aldığı değerler şunlardır: 1
EACCESS : Yol ifadesine ilişkin herhangi bir bileşene erişim hakkı yoktur ENAMETOOLONG : Yol ifadesi PATH_MAX değerinden daha uzundur ya da yol ifadesinin bir bileşeni NAME_MAX değerinden daha uzundur. ENOENT : Fonskiyonun paarametresi bir dizini belirtmemektedir ya da boş bir yazıdan oluşmaktadır ELOOP : Sembolik bağlantılardan dolayı döngüsel bir durum oluşmuştur.... :... Hata kodlarında da gördüğünüz gibi opendir fonksiyonuyla bir dizini açabilmeniz için her yol bileşenine ilişkin dizine x hakkınızın olması ( r hakkı gerekmiyor) ve ayrıca hedef dizine de r hakkınızın olması gerekir. Örneğin /usr/include dizinini açabilmeniz için usr ve include dizinleri için x hakkına ve ayrıca include dizini için de ayrıca r hakkına sahip olmalısınız. opendir fonksiyonunu şöyle kullanabilirsiniz: DIR *dir;... if ((dir = opendir("/usr/include")) == NULL) perror("opendir"); opendir fonksiyonuyla dizini açtıktan sonra artık readdir fonksiyonuyla dizin içerikleri elde edilebilir. readdir fonksiyonu her çağrıldığında bir sonraki dizin elemanını verecektir. Prototipini inceleyiniz: struct dirent *readdir(dir *dir); Fonksiyon opendir fonksiyonundan elde edilen handle değerini parametre olarak alır. Başarı durumunda dizin girişine ilişkin bilgilerin bulunduğu dirent isimli bir yapının adresiyle, başarısızlık durumunda NULL değeriyle geri döner. Başarısızlığın iki nedeni olabilir. Birinci ve muhtemel nedeni dizin listesinin sonuna gelinmesidir. Bu durum programcı tarafından normal karşılanmalıdır. İkinci durumda ise daha ciddi bir giriş/çıkış problemiyle karşılaşımıştır. Eğer fonksiyon dizin listesinin sonuna gelmekten dolayı başarısız olduysa errno değişkeninin değeri değişmez. Yok eğer fonksiyon ciddi bir okuma hatasından dolayı başarısız olmuşsa errno değişkenine hata değeri atanır. Hata durumunda errno değişkeninin alabileceği önemli değerler şunlardır: 2
EBADF : Fonksiyonun parametresi. ENOENT : Dizin okumasında hata oluşmuştur.... :... errno değişkeninin alabileceği diğer değerler için dökümanlara başvururabilirsiniz. i-node tabanlı sistemlerde dizin girişi tipik olarak dosya ismi ve i-node numarasından oluşmaktadır. dirent yapısı tipik olarak aşağıdaki gibidir: struct dirent char d_name[name_max]; ino_t d_ino; ; POSIX standartlarına göre dirent yapısı daha fazla eleman içerebilir. Fakat en azından dosyanın ismini belirten bir d_name elemanı ile düğüm numarasını belirten bir d_ino elemanının olması gerekir. dirent yapısı da <dirent.h> başlık dosyası içerisinde bildirilmiştir. opendir fonksiyonuyla açılan dizin closedir fonksiyonuyla kapatılmalıdır. closedir fonksiyonunun prototipi de şöyledir: int closedir(dir *dir); Fonksiyon açılan dizine ilişkin handle değeri parametre olarak alır ve açılmış olan dizini kapatır. closedir fonksiyonu başarı durumunda sıfır değerine başarısızlık durumunda -1 değerine geri döner. Dizin doğru bir biçimde açıldıysa kapatılamaması için bir neden yoktur. Bu nedenle fonksiyonun geri dönüş değerini kontrol etmeyebilirsiniz. Başarısızlık durumunda errno değişkeninin alacağı değerler için dökümanlara başvurabilirsiniz. Tıpkı dosyalarda olduğu gibi dizinler de prosesin sonlanmasıyla otomatik olarak kapatılmaktadır. Sonraki örneklerimizde bu nedenle exit fonksiyonuyla prosesi sonlandırmadan önce closedir fonksiyonunu uygulamayacağız. Dizin içerisindeki dosyaların isimlerini tipik olarak aşağıdaki gibi elde edebiliriz: 3
/* dirlist1.c */ #include <stdio.h> #include <stdlib.h> void err_sys(const char *msg) perror(msg); fflush(stdout); int main(void) DIR *dir; struct dirent *ent; if ((dir = opendir("/usr/include")) == NULL) err_sys("opendir"); while ((ent = readdir(dir))!= NULL) printf("%s\n", ent->d_name); closedir(dir); return 0; Derlemeyi şöyle yapabilirsiniz: gcc o dirlist1 dirlist1.c Döngünün her yinelenmesinde yeni bir dosyanın bilgileri elde edilmektedir. Nihayet dizin listesi bittiğinde readdir fonksiyonu NULL değerine geri döner ve döngüden çıkılır. Tabi burada yalnızca dizin listesi bittiğinde değil bir giriş/çıkış hatası olduğunda da readdir fonksiyonu NULL ile geri döneceğinden döngüden çıkılacaktır. Giriş/çıkış hatası olasılığını gözardı edebilirsiniz. Çünkü herşeyi düzgün yaptığınız bir durumda böyle bir hatanın ortaya çıkma olasılığı da yoktur. Fakat tam bir hata denetimi sağlamak istiyorsanız başarısızlığın nedenini tespit etmelisiniz. Bunun için readdir fonksiyonunu çağırmadan önce errno değişkenine değer atanmalı, döngü çıkışında bu değere bakılmalıdır. /* dirlist2.c */ #include <stdio.h> #include <stdlib.h> #include <errno.h> 4
void err_sys(const char *msg) perror(msg); int main(void) DIR *dir; struct dirent *ent; if ((dir = opendir("/usr/include")) == NULL) err_sys("opendir"); while (errno = 0, (ent = readdir(dir))!= NULL) printf("%s\n", ent->d_name); if (errno) err_sys("readdir"); closedir(dir); return 0; Derleme işlemi şöyle yapılabilir: gcc o dirlist2 dirlist2.c rewinddir fonksiyonu listeleme işlemini baştan başlatmak için kullanılmaktadır. Örneğin, opendir fonksiyonuyla dizini açtıktan sonra listeleme yaptınız, fakat closedir ile dizini kapatmadan bu işlemi bir kez daha yapmak istiyorsunuz. İşte bu durumda rewinddir ile dizinin yeniden başına geçebilirsiniz: void rewinddir(dir *dir); telldir fonksiyonu listeleme sırasında dizinde bulunulan konumu almak için kullanılır: long telldir(dir *dir); Alınan offset çoğu POSIX kütüphanesinde dizin içerisinde o anda bulunulan dosya sırasına ilişkin indeks numarası belirtse de standart genelinde böyle bir garanti verilmemiştir. Yani fonksiyon dizin içerisinde kalınan yeri belirten bir sayı vermektedir fakat bu sayının nasıl elde edileceği derleyicileri yazanların isteğine bırakılmıştır. seekdir fonksiyonu telldir fonksiyonu ile alınan konuma geri dönmek için kullanılmalıdır: 5
void seekdir(dir *dir, off_t offset); Fonksiyonun ikinci parametresi telldir fonksiyonundan alınan değeri belirtir. Fonksiyon dizin içerisinde daha önce alınmış pozisyona konumlandırma yapar. Dizin içeriğini listelemek için verdiğimiz bu örneklerde yalnızca dosyaların isimlerini yazdırdık. Peki dosyaların diğer özelliklerini nasıl yazdıracağız? İşte readdir fonksiyonuyla dosyaların düğüm isimlerini elde ettikten sonra stat fonksiyonuyla onların bilgilerini elde edebiliriz. Dizin listesini almakta kullandığımız ls programı da tamamen bu biçimde çalışmaktadır. Aşağıdaki program komut satırı argümanı olarak verilen dizin içerisindeki dosyaları listeliyor, inceleyiniz: /* dirlist3.c */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #define MAX_PATH_LEN 1024 void err_sys(const char *msg) perror(msg); int main(int argc, char *argv[]) DIR *dir; struct dirent *ent; struct stat finfo; char path[max_path_len]; int result; if (argc!= 2) fprintf(stderr, "Wrong number of arguments!..\n"); if ((dir = opendir(argv[1])) == NULL) err_sys("opendir"); while (errno = 0, (ent = readdir(dir))!= NULL) snprintf(path, MAX_PATH_LEN, "%s/%s", argv[1], ent->d_name); if (stat(path, &finfo) < 0) err_sys("stat"); 6
printf("%-40s", ent->d_name); if (S_ISDIR(finfo.st_mode)) printf("<dir>\n"); else printf("%lu\n", finfo.st_size); if (errno) err_sys("readdir"); closedir(dir); return 0; Derleme işlemini aşağıdaki gibi yapabilirsiniz: gcc o dirlist3 dirlist3.c Programı çalıştırırken komut satırı argümanı olarak listelemek istediğiniz dizini vermelisiniz. Örneğin:./dirlist3 /usr/include Programda önce komut satırı argümanlarının sayısının kontrol edildiğini görüyorsunuz. Sonra opendir fonksiyonu ile dizin açılmış ve döngü içerisinde readdir fonksiyonu ile dizin girişleri okunarak stat fonksiyonu ile dosya bilgilerine erişilmiştir. Burada önemli bir anımsatma yapmak istiyoruz. stat fonksiyonu bizden dosyanın tüm yol ifadesini istemektedir. Halbuki readdir fonksiyonuyla yalnızca dosyanın ismini elde edebiliyoruz. O halde readdir fonksiyonuyla elde ettiğimiz dosya ismini dizinin yol ifadesiyle birleştirerek tüm yol ifadesini elde etmeliyiz. Bu işlem programda şöyle yapılmıştır snprintf(path, MAX_PATH_LEN, "%s/%s", argv[1], ent->d_name); snprintf fonksiyonu sprintf gibidir fakat bir güvenlik parametresi vardır. Fonksiyon en fazla bu sayıda (null karakter dahil olmak üzere) karakteri hedef diziye yazar. Diziyi neden 1024 byte uzunlukta açtığımızı merak edebilirsiniz. Bu kadar geniş açmamızın nedeni çok uzun dosya isimlerinin probleme yol açmasını engellemektir. Bir dosya isminin ya da yol ifadesinin POSIX sistemlerinde en fazla hangi uzunlukta olabileceği konusunun bazı ayrıntıları olduğu için burada kodu karıştırmak istemedir. Aslında her defasında readdir ile elde ettiğimiz dosya ismini yol ifadesiyle birleştirmek yerine prosesin çalışma dizinini de chdir fonksiyonuyla değiştirebilirdik. Bu durumda program aşağıdaki gibi olurdu: /* dirlist4.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> 7
void err_sys(const char *msg) perror(msg); int main(int argc, char *argv[]) DIR *dir; struct dirent *ent; struct stat finfo; int result; if (argc!= 2) fprintf(stderr, "Wrong number of arguments!..\n"); if ((dir = opendir(argv[1])) == NULL) err_sys("opendir"); if (chdir(argv[1]) < 0) err_sys("chdir"); while (errno = 0, (ent = readdir(dir))!= NULL) if (stat(ent->d_name, &finfo) < 0) err_sys("stat"); printf("%-30s", ent->d_name); if (S_ISDIR(finfo.st_mode)) printf("<dir>\n"); else printf("%lu\n", finfo.st_size); if (errno) err_sys("readdir"); closedir(dir); return 0; Dizin değiştirme işlemi şöyle yapılmıştır: if (chdir(argv[1]) < 0) err_sys("chdir"); Bu işlemden sonra artık prosesin çalışma dizini (current working directory) komut satırında belirtilen dizin olacaktır. Bu nedenle stat fonksiyonuna verilen dosya ismine herhangi bir ekleme yapmaya gerek duyulmamıştır. readdir fonksiyonuyla dosyaların elde edilme sıralarının isme ya da uzunluğa göre olmadığını belirtelim. Dosyalar dizin içerisindeki doğal sıraya göre elde edilmektedir. Doğal sıra, dizin dosyası içerisindeki dizin girişlerinin oluşturulma sırasıdır. Tabi bir 8
dosya silindiğinde yeni gelen dosya listenin sonuna değil, silinmiş olan girişin yerine girebilir. Bu durumda elde edilen sıranın dizin girişlerinin yaratılma zamanlarına ilişkin olduğunu bile söyleyemeyiz. Eğer dosyaları isme ya da uzunluğa göre listelemek istiyorsanız önce onları dinamik büyütülen bir dizide toplamanız daha sonra da sıralamanız gerekir. Bu işlemi C++'da aşağıdaki gibi yapabilirsiniz: /* dirlist5.cpp */ #include <iostream> #include <cstdlib> #include <iterator> #include <algorithm> #include <string> #include <vector> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> using namespace std; void err_sys(const char *msg) perror(msg); int main(int argc, char *argv[]) DIR *dir; struct dirent *ent; struct stat finfo; int result; vector<string> dirlist; if (argc!= 2) cerr << "Wrong number of arguments!"; if ((dir = opendir(argv[1])) == NULL) err_sys("opendir"); if (chdir(argv[1]) < 0) err_sys("chdir"); while (errno = 0, (ent = readdir(dir))!= NULL) if (stat(ent->d_name, &finfo) < 0) err_sys("stat"); dirlist.push_back(ent->d_name); 9
if (errno) err_sys("readdir"); closedir(dir); sort(dirlist.begin(), dirlist.end()); copy(dirlist.begin(), dirlist.end(), ostream_iterator<string>(cout, "\n")); return 0; Burada vector içerisinde biz yalnızca dosya isimlerini tuttuk. Siz istersenin dosyanın stat bilgilerini de tutabilirsiniz. Derleme işlemini şöyle yapabilirsiniz: g++ -o dirlist5.cpp dirlist5.cpp Windows sistemlerinde dizin içeriğinin elde edilmesi POSIX sistemlerine benzer bir biçimde yapılmaktadır. FindFirstFile isimli API fonksiyonuna içeriği elde edilecek dosyalara ilişkin yol ifadesi verilir ve fonksiyondan bir handle değeri elde edilir. Bu fonksiyon aynı zamanda koşulu sağlayan ilk dosyanın bilgilerini de almaktadır. Daha sonra bir döngü içerisinde FindNextFile fonksiyonuyla diğer dosyalar elde edilir. Nihayet açılmış olan handle alanı FindClose fonksiyonuyla serbest bırakılır. FindFirstFile fonksiyonunun prototipi şöyledir: #include <windows.h> HANDLE FindFirstFile( LPCTSTR lpfilename, LPWIN32_FIND_DATA lpfindfiledata ); Fonksiyonun birinci parametresi bilgisi elde edilecek dosyaya ilişkin yol ifadesini (path name) belirtir. Yol ifadesi * ve? joker karakterlerini içerebilir. Bu durumda fonksiyon koşulu sağlayan ilk dosyanın bilgilerini elde eder. Fonksiyonun ikinci parametresi dosya bilgilerinin yerleştirileceği WIN32_FIND_DATA türünden yapının adresini alır. Fonksiyon dosya bilgilerini bu yapıya yerleştirmektedir. WIN32_FIND_DATA yapısı şöyledir: 10
#include <windows.h> typedef struct _WIN32_FIND_DATA DWORD dwfileattributes; FILETIME ftcreationtime; FILETIME ftlastaccesstime; FILETIME ftlastwritetime; DWORD nfilesizehigh; DWORD nfilesizelow; DWORD dwreserved0; DWORD dwreserved1; TCHAR cfilename[max_path]; TCHAR calternatefilename[14]; WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA; Yapının cfilename elemanı dosyanın ismini calternatefilename elemanı ise MSDOS uyumlu 8+3 lük kısa dosya ismini bulundurmaktadır. dwfileattributes elemanı dosyanın özelliklerini tutar. Bu eleman bit bit anlamlıdır ve ilgili özelliğin dosyada olup olmadığını belirlemek için tüm bitleri 0 olan yalnızca ilgili biti 1 olan değerlerle & işlemi uygulamak gerekir. Özelliklere ilişkin maskeleme değerleri <Windows.h> (alt dosya olarak <Winnt.h>) içerisinde bildirilmiştir. Bu değerlerden bazılarını aşağıda görüyorsunuz: #define FILE_ATTRIBUTE_READONLY #define FILE_ATTRIBUTE_HIDDEN #define FILE_ATTRIBUTE_SYSTEM #define FILE_ATTRIBUTE_DIRECTORY #define FILE_ATTRIBUTE_ARCHIVE... 0x00000001 0x00000002 0x00000004 0x00000010 0x00000020 Yapının ftccreationtime, ftlastaccesstime ve ftlastwritetime elemanları dosyanın yaratılış zamanını, son erişim zamanını ve son güncelleme zamanını tutmaktadır. (FAT12 ve FAT16 sistemlerinde yalnızca son güncelleme zamanı tutulmaktadır.) FILETIME iki DWORD ten oluşan aşağıdaki gibi bir yapıdır: #include <windows.h> typedef struct _FILETIME DWORD dwlowdatetime; DWORD dwhighdatetime; FILETIME, *PFILETIME, *LPFILETIME; Yapıdaki 64 bitlilk değer 01/01/1601 tarihinden itibaren geçen 100 nano saniyelerin sayısını UTC (eski ismiyle GMT) olarak verir. FILETIME yapısını tarih ve zaman bilgisine dönüştüren FileTimeToSystemTime fonksiyonunu kullanabilirsiniz. FileTimeToLocalFileTime fonksiyonu ise UTC yi yerel zamana dönüştürmektedir. Yapının nfilesizehigh ve nfilesizelow elemanları dosya uzunluğunu veren 64 bit değeri belirtiyor. Bu iki değeri Microsoft un int64 türüne (ya da C99 ve C++0x in long long türüne) dönüştürmek için LARGE_INTEGER birliği kullanılabilir: 11
#include <windows.h> typedef union _LARGE_INTEGER struct DWORD LowPart; LONG HighPart; u; LONGLONG QuadPart; LARGE_INTEGER, *PLARGE_INTEGER; Dönüştürmeyi şöyle yapabilirsiniz: LARGE_INTEGER li; WIN32_FIND_DATA fd; int64 fs;... li.u.lowpart = fd.nfilesizelow; li.u.highpart = fd.nfilesizehigh; fs = li.quadpart; FindFirstFile fonksiyonunun geri dönüş değeri FindNextFile fonksiyonu için kullanılacak handle değeridir. Fonksiyon başarısızlık durumunda INVALID_HANDLE_VALUE değerine geri döner. FindFirstFile fonksiyonunu aşağıdaki gibi kullanabilirsiniz: HANDLE hfind; WIN32_FIND_DATA fd; if ((hfind = FindFirstFile(_T("C:\\Windows\\*.exe"), &fd)) == INVALID_HANDLE_VALUE) _ftprintf(stderr, _T("Cannot find file, GetLastError = %u\n"), GetLastError()); FindFirstFile fonksiyonunu UNIX/Linux istemlerindeki opendir fonksiyonuna benzetebiliriz. Ancak gördüğünüz gibi Windows sistemlerinde bu fonksiyon joker karakterleri de alarak yalnızca belli koşulu sağlayan dosyaları bulabilmektedir. Windows sistemlerinde koşulu sağlayan diğer dosyaların bulunması FindNextFile fonksiyonuyla yapılmaktadır: #include <windows.h> BOOL WINAPI FindNextFile( HANDLE hfindfile, LPWIN32_FIND_DATA lpfindfiledata ); Fonksiyonun birinci parametresi FindFirstFile fonksiyonundan alınan handle değerini ikinci parametresi ise bulunan dosya bilgilerinin yerleştirileceği WIN32_FIND_DATA yapısının adresini alır. Fonksiyon başarı durumunda sıfır dışı bir değere başarısızlık durumunda sıfır değerine geri döner. Başarısızlığın tipik nedeni listenin sonuna gelinmesidir (yani bulunacak dosyanın kalmamasıdır). Bu durumda GetLasrError 12
fonksiyonu ERROR_NO_MORE_FILES değerine geri döner. FindClose fonksiyonuyla handle alanı kapatılmalıdır: İşlemler bitince #include <windows.h> BOOL WINAPI FindClose( HANDLE hfindfile ); Şimdi Windows ta dizin listesinin elde edilmesine yönelik bir örnek verelim. Örnekte C:\Windows dizininin içeriği listeleniyor. Fakat siz bu örnekten hareketle kodu istediğiniz gibi düzenleyebilirsiniz #include <stdio.h> #include <stdlib.h> #include <math.h> #include <Windows.h> #include <Tchar.h> void DispFileInfo(const WIN32_FIND_DATA *pfd); int main(void) HANDLE hfind; WIN32_FIND_DATA fd; if ((hfind = FindFirstFile(_T("C:\\Windows\\*.*"), &fd)) == INVALID_HANDLE_VALUE) _ftprintf(stderr, _T("FindFirstFile error: %u\n"), GetLastError()); do DispFileInfo(&fd); while (FindNextFile(hFind, &fd)); if (GetLastError()!= ERROR_NO_MORE_FILES) _ftprintf(stderr, _T("FindFirstFile error: %u\n"), GetLastError()); FindClose(hFind); return 0; void DispFileInfo(const WIN32_FIND_DATA *pfd) LARGE_INTEGER li; int64 fs; SYSTEMTIME st; li.u.lowpart = pfd->nfilesizelow; li.u.highpart = pfd->nfilesizehigh; fs = li.quadpart; 13
FileTimeToSystemTime(&pfd->ftLastWriteTime, &st); _tprintf(_t("%02d/%02d/%04d %02d:%02d "), st.wday, st.wmonth, st.wyear, st.whour, st.wminute); if (pfd->dwfileattributes & FILE_ATTRIBUTE_DIRECTORY) _tprintf(_t("%-18s"), _T("<DIR>")); else _tprintf(_t("%18i64u"), fs); _tprintf(_t(" %s\n"), pfd->cfilename); Ayrıca Windows Xp, 2000 ve Vista sistemlerine daha yetenekli yeni bir FindFirstFileEx fonksiyonu da eklenmiştir: #include <windows.h> HANDLE WINAPI FindFirstFileEx( LPCTSTR lpfilename, FINDEX_INFO_LEVELS finfolevelid, LPVOID lpfindfiledata, FINDEX_SEARCH_OPS fsearchop, LPVOID lpsearchfilter, DWORD dwadditionalflags ); Gördüğünüz gibi fonksiyon yetenek olarak oldukça geliştirilmiştir. Fonksiyonun ikinci ve dördüncü parametreleri daha çok geleceğe uyum için düşünülmüştür. Bu fonksiyon büyük harf küçük harf duyarlılığı ile de arama yapabilmektedir. Son olarak ayrı bir FindNextFileEx gibi bir fonksiyonun olmadığını belirtelim. FindFirstFileEx fonksiyonundan alınan handle değeri FindNextFile fonksiyonunda kullanılmaktadır. Java ve C# gibi nesne yönelimli programlama dillerinin kütüphanelerinde dizin içeriğini elde etmek için çeşitli sınıflar ve metotlar bulunmaktadır. Şüphesiz bu metotlar UNIX/Linux ve Windows sistemlerinde yukarıda belirttiğim sistem fonksiyonlarını kullanıyorlar..net kütüphanesinde System.IO isim alanındaki Directory sınıfının GetFiles isimli static metotları bir dizin içerisindeki dosyaları bulmak için kullanılmaktadır: public static string[] GetFiles( string path ) public static string[] GetFiles( string path, string searchpattern ) 14
public static string[] GetFiles( string path, string searchpattern, SearchOption searchoption ) Birinci metot dizin içerisindeki dosyaların hepsini, ikinci metot joker karakterleriyle verilen koşulu sağlayan dosyaları bulmaktadır. Üçüncü metot ise alt dizinlerde özyinelemeli arama yapabilmektedir. Benzer biçimde dizin içerisindeki dizinler de yine Directory sınıfının GetDirectories metotlarıyla elde edilebilir: public static string[] GetDirectories( string path ) public static string[] GetDirectories( string path, string searchpattern ) public static string[] GetDirectories( string path, string searchpattern, SearchOption searchoption ) Bu sınıflar ve metotlar Linux ve MacOS X sistemlerinde Mono altında da aynı biçimde kullanılabilir. Aşağıda bir örnek görüyorsunuz: using System; using System.IO; namespace CSD class Application public static void Main() try string[] files = Directory.GetFiles(@"C:\Windows"); foreach (string file in files) Console.WriteLine(file); string [] dirs = Directory.GetDirectories(@"C:\Windows"); foreach (string file in files) Console.WriteLine(file + " <DIR>"); 15
catch (Exception e) Console.WriteLine(e.Message); Bu metotların dosya isimlerini yol ifadeleriyle birlikte elde ettiğini belirtelim..net sisteminde dosya bilgileri FileInfo, dizin bilgileri ise DirectoryInfo sınıfı kullanılarak elde edilebilir. Java da dizin listesi System.io paketi içerisinde bulunan File sınıfı ile elde edilebilir. File sınıfının static olmayan list ve listfiles metotlarıyla dizin listesi elde edilebilir. Genel kullanım biçimi.net teki karşılığına benzemektedir. Aşağıda bir örnek görüyorsunuz: import java.io.*; class Main public static void main(string[] args) File dir = new File("c:\\windows"); String[] files; if ((files = dir.list()) == null) System.out.println("Cannot get files!"); System.exit(1); for(string s : files) System.out.println(s); list metotları hem dosyaları hem de dizinleri bulmaktadır. Bu metotlar dosya ismini yol ifadesi olmaksızın elde ederler. listfiles metotları ise dizin içeriğini File dizisi biçiminde vermektedir. [1] Linux sistemlerinde dizin listesini elde etmek için dizin önce open sistem fonksiyonuyla açılır ver getdents (eskiden readdir) sistem fonksiyonuyla okunur. 16