2010-02-12 130 views
3

我試圖在主例程中使用rm命令來刪除一個我已經使用命令行參數的文件。該值存儲在argv[2]我一直在使用在c程序中使用stdlib.h中的system()函數使用'rm'命令

system("rm argv[2]"); 

system("rm ./argv[2]"); 

system("rm $HOME/argv[2]"); 

嘗試,但它給了我一個錯誤說

"cannot locate file argv[2]"

的文件名保存在argv[2]因爲我已經檢查了它。

有人請指導我!

回答

15

爲什麼不使用removeunlink命令代替system("rm ...")

remove(argv[2]);unlink(argv[2]);


更新的情況下system("rm ...")必須使用

如果必須使用system("rm ...")ZelluX是指出必須從argv[2]檢索文件名是正確的。您可以使用snprintfstrncpy檢索字符串argv[2]。使用限制輸入大小的函數的變體是good idea,因爲不能保證argv[2]中字符串的長度。

根據您的應用程序,你可能還需要調用stat來驗證argv[2]字符串確實是一個文件,並可能限制文件的類型。

實施例:

此示例調用stat驗證argv[2]是一個普通文件和asprintf動態爲緩衝區分配空間。

char *p; 
struct stat st; 

if (stat(argv[2], &st) == 0 && S_ISREG(st->st_mode)) 
{ 
    if (asprintf(&p, "rm %s", argv[2]) != -1) 
    { 
     system(p); 
     free(p); 
    } 
} 
+1

我只能假設這有四個upvotes之前的可怕壞建議「你仍然需要檢索字符串argv [2]使用snprintf或strncpy」被添加。如果你不打算修改它,除了增加緩衝區溢出的機會之外,還有什麼地方可以將字符串複製到一個新的字符串? – Miles 2010-02-12 07:17:49

+0

不知道如何使用snprintf或strncpy進行緩衝區溢出,但是您確實無需執行此步驟。答案回滾。 – jschmier 2010-02-12 07:21:00

+1

這個問題沒有這麼說,但你可以使用argv [2]將參數傳遞給rm,在這種情況下,unlink不起作用:-) – 2010-02-12 07:23:11

8

「rm ./argv[2]」中的「argv [2]」是一個文字字符串,如果要使用argv [2]中存儲的內容,則需要使用strcpy()或sprintf( )將「rm ./」與存儲在argv [2]中的字符串連接起來。

+0

@Zellux +1太棒了! – 2010-02-12 06:59:24

+1

我建議使用** strncpy()**或** snprintf()**來覆蓋** strcpy()**或** sprintf()**來限制複製的字符數以避免緩衝區溢出,因爲字符串通過'argv [2]'傳入'是任意長度的。 – jschmier 2010-02-12 17:49:05

1

您需要先構造字符串。只要將argv [2]放在引號中就行不通。

例子:

char buf[256]; 

buf[255] = '\0'; 
if (snprintf(buf, 255, "rm %s", argv[2]) != -1) { 
    system(buf); 
} 
+0

這有一個緩衝區溢出(最後一個元素是'buf [255]')。也就是說,snprintf將始終寫入一個0結束符,因此不需要手動添加一個結束符。另外,調用snprintf時不需要從數組長度中減去1。 – 2010-02-12 07:38:55

+0

是的,錯字。我會糾正這一點。我打算使用buf [255],這就是爲什麼使用255調用snprintf的原因。不知道snprintf行爲(可能取決於您使用的操作系統/庫)。如果緩衝區足夠長,它只會在最後加0。所以有些情況下你可能還會錯過它。 – 2010-02-12 07:43:14

2

argv [2]包含字符串,它本身不是字符串。請使用strcpy或其他字符串操作機制將argv [2]中的字符串獲取到緩衝區中,然後使用rm構造一個命令,然後將其傳遞給系統。這應該工作。

2

,而不是調用系統rm命令,這樣做在C,如

#include <stdio.h> 
#include <dirent.h> 
int main() 
{ 
     struct dirent *d; 
     DIR *dir; 
     char buf[256]; 
     dir = opendir("mydir"); 
     while(d = readdir(dir)) 
     {    
       sprintf(buf, "%s/%s", "mydir", d->d_name); 
       remove(buf); 
     } 
     return 0; 

} 
2

參見取消鏈接(2)(在unistd.h中定義),如果你想刪除文件,而無需調用系統()。

0

問題是,argv [2]沒有得到擴展,並且像那樣傳遞,因爲沒有名爲argv [2]的文件,將會出現錯誤。 的溶液。將產生一個使用字符串的sprintf(),然後將它傳遞給系統()

char str[100]; 
sprintf(str,"rm %s",argv[2]); 
system(str); 
1

使用system這樣的(事實上,利用它在所有)可以災難的公式。假設argv[2]包含"-rf /"。 :-)

+0

+1:你確實有一點,雖然有限的用戶權限可能會阻止你這樣做=) – rubenvb 2010-07-26 13:27:41

+0

這只是一個例子。更大的問題是,使用'system'要求你考慮(1)shell在將字符串傳遞給程序之前如何解釋字符串,以及(2)程序如何錯誤地解釋爲部分或全部字符串旨在被解釋爲文件名。可以通過適當的轉義來解決這些問題(反斜槓或shell引用和'--'轉換爲'rm'),但是值得冒這個風險嗎? – 2010-07-26 13:41:47

0

實際上argv[2]是一個字符串,您將它用作文件名,以便將其用作需要連接的字符串。這就是您無法找到名稱爲argv[2]的文件的原因,而不是文件名是字符數組argv[2]。嘗試不同的連接方法。

相關問題