linux glob函数详解
glob庫函數(shù)用于Linux文件系統(tǒng)中路徑名稱的模式匹配,即查找文件系統(tǒng)中指定模式的路徑。注意,這不是正則表達(dá)式匹配,雖然有些相似,但還是有點(diǎn)差別。
glob函數(shù)原型
?????? #include <glob.h>
?????? int glob(const char *pattern,?int flags,
?????????????????????????? int errfunc(const char *epath, int eerrno),
?????????????????????????? glob_t *pglob);
?????? glob函數(shù)搜索匹配 函數(shù)pattern中的參數(shù),如/*是匹配根文件下的所有文件(不包括隱藏文件,要找的隱藏文件需要從新匹配),然后會(huì)將匹配出的結(jié)果存放到 pglob,即第4個(gè)參數(shù)中,第二個(gè)參數(shù)能選擇匹配模式,如是否排序,或者在函數(shù)第二次調(diào)用時(shí),是否將匹配的內(nèi)容追加到pglob中,等,第3個(gè)參數(shù)是查看錯(cuò)誤信息用,一般置為NULL;
具體可以在終端下輸入 man glob
實(shí)例1:
1 #include <stdio.h> 2 #include <glob.h> 3 4 int main(int argc, const char *argv[]) 5 { 6 glob_t buf; 7 int i; 8 glob("/dev/*",GLOB_NOSORT, NULL, &buf); 9 10 for(i=0; i < buf.gl_pathc; i++) 11 { 12 printf("buf.gl_pathv[%d]= %s \n", i, (buf.gl_pathv[i])); 13 } 14 15 globfree(&buf); 16 return 0; 17 } 18?
實(shí)例2:
在linux編程中,有時(shí)候會(huì)用到批量處理文件。比如寫一個(gè)上傳工具,用戶輸入文件名,如果此時(shí)用戶使用的是匹配的文件名,那么程序應(yīng)該做到根據(jù)匹配字符串自動(dòng)搜索符合要求的文件名的功能。
linux有一個(gè)glob函數(shù),可以做到這一點(diǎn),該函數(shù)位于頭文件glob.h中
事例:
1 #include <iostream> 2 3 #include <string> 4 5 #include <glob.h> 6 7 using namespace std; 8 9 10 11 void print_gl(glob_t &gl) 12 13 { 14 15 for(int i=0;i<gl.gl_pathc;i++) 16 17 { 18 19 cout<<gl.gl_pathv[i]<<endl; 20 21 } 22 23 } 24 25 26 27 void test_glob(int argc , char **argv) 28 29 { 30 31 glob_t gl; 32 33 for(int i=1;i<argc;i++) 34 35 { 36 37 gl.gl_offs=0; 38 39 glob(argv[i],GLOB_TILDE,0,&gl); 40 41 print_gl(gl); 42 43 globfree(&gl); 44 45 } 46 47 } 48 49 50 51 int main(int argc,char **argv) 52 53 { 54 55 if(argc<2) 56 57 { 58 59 cout<<"<file name>"<<endl; 60 61 return 0; 62 63 } 64 65 66 67 test_glob(argc,argv); 68 69 return 0; 70 71 }?
實(shí)例3:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include <glob.h> 6 7 static int test_fun(int, char *[]); 8 static void print_gl(glob_t *); 9 10 int main(int argc, char *argv[]) 11 { 12 if(argc > 1) 13 test_fun(argc, argv); 14 else 15 printf("./mytest {/"path list/"}/n"); 16 return 0; 17 } 18 19 static int test_fun(int argc, char *argv[]) 20 { 21 glob_t gl; 22 for(int i = 1; i < argc; ++i) { 23 gl.gl_offs = 0; 24 glob(argv[i], GLOB_TILDE, 0, &gl); 25 print_gl(&gl); 26 globfree(&gl); 27 } 28 return 0; 29 } 30 31 static void print_gl(glob_t *gl) 32 { 33 for(unsigned int i = 0; i < gl->gl_pathc; ++i) 34 printf("%s/n", gl->gl_pathv[i]); 35 printf("++++++++++++++++++++++/n"); 36 } 編譯:
gcc -std=c99 -g -W -Wall -Wextra -o mytest main.c
執(zhí)行示例:
./mytest "./*.cpp" "./*.h" "./make*" "~/p*/p?ng"
注意:上訴命令中引號(hào)是必需的,否則shell會(huì)將模式展開!
?
實(shí)例4:
用glob的遞歸調(diào)用可以找到系統(tǒng)任意路徑的所有文件。如下例子:
1 #include <stdio.h> 2 #include <glob.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <unistd.h> 8 9 static int OpenDir(const char *buf) 10 { 11 int ret; 12 char path[50] = {0}; 13 char temp[50] = {0}; 14 char *tp = NULL; 15 glob_t globbuf; 16 struct stat fileinfo; 17 int i; 18 char *ptr = NULL,*last_ptr = NULL; 19 strcpy(path,buf); 20 if(buf[strlen(buf)- 1] == '/') 21 strcat(path,"*"); 22 else 23 strcat(path,"/*"); 24 if((ret = glob(path,GLOB_NOSORT,NULL,&globbuf)) != 0){ 25 if(GLOB_NOMATCH == ret) 26 return 0; 27 else 28 return -1; 29 } 30 strcpy(path,buf); 31 if(buf[strlen(buf)- 1] == '/') 32 strcat(path,".*"); 33 else 34 strcat(path,"/.*"); 35 36 if((ret = glob(path,GLOB_APPEND,NULL,&globbuf)) != 0){ 37 if(GLOB_NOMATCH == ret) 38 return 0; 39 else 40 return -1; 41 } 42 for(i = 0;i < globbuf.gl_pathc;i++){ 43 ret = lstat(globbuf.gl_pathv[i],&fileinfo); 44 if(ret != 0){ 45 perror("lstat()"); 46 return -1; 47 } 48 if(1 == S_ISDIR(fileinfo.st_mode)){ 49 printf("\n%s is directory!\n",globbuf.gl_pathv[i]); 50 strcpy(temp,globbuf.gl_pathv[i]); 51 tp = temp; 52 while((last_ptr = strsep(&tp,"/")) != NULL){ 53 ptr = last_ptr; 54 } 55 if((strcmp(ptr,".") == 0) || (strcmp(ptr,"..") == 0)) 56 continue; 57 ret = OpenDir(globbuf.gl_pathv[i]); 58 if(ret != 0){ 59 printf("*****opendir() error!\n"); 60 } 61 } 62 else 63 { 64 printf("%s\n",globbuf.gl_pathv[i]); 65 } 66 } 67 return 0; 68 } 69 int main(int argc, char *argv[]) 70 { 71 glob_t globbuf; 72 int ret ; 73 struct stat fileinfo; 74 int i; 75 if(argc != 2){ 76 printf("argument error!\n"); 77 } 78 ret = OpenDir(argv[1]); 79 if(ret != 0){ 80 printf("opendir() error!\n"); 81 return -1; 82 } 83 return 0; 84 } 執(zhí)行如下命令獲取當(dāng)前路徑中所有文件:
[tom@localhost glob]$ ./glob ./
./dir2 is directory!
./glob.c
./glob
./dir1 is directory!
./dir1/file2
./dir1/file1
./dir1/. is directory!
./dir1/.. is directory!
./. is directory!
./.. is directory!
可以看到 當(dāng)前路徑下有dir1 和dir2 兩個(gè)目錄,其中dir2為空目錄,dir1中有file1和file2兩個(gè)文件,.和..兩個(gè)隱藏文件以及程序源碼glob.c和可執(zhí)行程序文件glob。
注意:
假設(shè)你有一個(gè)文件夾,你要?jiǎng)h除里面類似這樣命名的文件 :; ?1 t& z??j3 M9 N9 r' D- t; g
/path/to/dir/000000 - Smooth Faker
/path/to/dir/000000 - Rubber Hocker8 w/ C( r5 S. v" P! w- N+ e% {
...S2nS2n?q0 t2 w
, F/ r" _! \* ~: V6 k/ x( _
在 perl 里你可以用很多方法得到這樣的文件列表(TIMTOWTDI),諸如opendir后grep, find函數(shù),當(dāng)然還有更容易讓shell迷想起的glob函數(shù)。 不過關(guān)于glob函數(shù),這里有個(gè)很大的陷阱,如果不注意他將可能導(dǎo)致災(zāi)難后果,比如:. i??K" a. T% t??^
, s5 z. J8 R* t8 C
unlink glob("/path/to/dir/000000 - *");1 u' F2 |! P! P
看上去似乎沒問題,但這個(gè)危險(xiǎn)的操作可以刪除你當(dāng)前文件下的的所有文件。
; t; _HH?~
讓我們仔細(xì)看文檔, perldoc File::Glob :
? ?? ? Since v5.6.0, Perl’s CORE::glob() is implemented in terms of' Y3 R$ R- ^0 b9 |* h. j
? ?? ? bsd_glob().??Note that they don’t share the same
? ?? ? prototype--CORE::glob() only accepts a single argument.??Due to
? ?? ? historical reasons, CORE::glob() will also split its argument on% e% t6 u- ]??q' b9 \( q6 j7 W& O$ J0 N; U
? ?? ? whitespace, treating it as multiple patterns, whereas bsd_glob()/ iN!?j#?YN!?j#?Y?}# g
? ?? ? considers them as one pattern.
也就是說,這里的 glob 操作變成了, File::Glob::bsd_glob("/path/to/dir/00000", "-", "*"), 你將會(huì)刪掉'*'匹配的所有文件。解決辦法是用雙引號(hào)括起整個(gè)部分,或者使用File::Glob::bsd_glob。
- r- J" O9 \7 ?3 i( H
按理這個(gè)是已經(jīng)在文檔中說明了,不應(yīng)該算是陷阱,不過如果你僅僅用 perldoc -f glob 查看,那么并沒有類似的說明和警告而是讓你轉(zhuǎn)而看 File::Glob 的說明。(常常的)偷懶和想當(dāng)然的結(jié)果就是,忽視了這里最大的一個(gè)可能引爆的漏洞。所以這里的建議是不使用glob而是使用File::Glob::bsd_glob
總結(jié)
以上是生活随笔為你收集整理的linux glob函数详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IPC之IPC_PRIVATE与ftok
- 下一篇: Arrays类中的fill(用于填充数组