rename

rename

rename是一個計算函式,功能是給一個檔案重命名,用該函式可以實現檔案移動功能,把一個檔案的完整路徑的盤符改一下就實現了這個檔案的移動。

C語言庫函式

頭檔案:在Visual C++6.0中用stdio.h或者io.h

用 法: int rename(char *oldname, char *newname);

程式例:

#include

int main(void)

{

char oldname[80], newname[80];

/* prompt for file to rename and new name */

printf("File to rename: ");

gets(oldname);

printf("New name: ");

gets(newname);

/* Rename the file */

if (rename(oldname, newname) == 0)

printf("Renamed %s to %s.\n", oldname, newname);

else

perror("rename");

return 0;

}

執行過程:

File to rename: D:\\in.dat

New name: G:\\in.dat

Renamed D:\\in.dat to G:\\in.dat.

這樣就實現了in.dat從D糟移動到G盤。

在unix或linux系統中:

#include

int rename(const char *oldname, const char *newname);

函式說明

(1) 如果oldname為一個檔案而不是目錄,那么為該檔案更名。在這種情況下,如果newname作為一個目錄已存在,則它不能重命名一個目錄。如果newname已存在,而且不是一個目錄,則先將其刪除然後將oldname更名為newname。對oldname所在目錄以及newname所在的目錄,調用進程必須具有寫許可權,因為將更改這兩個目錄。

(2) 如若oldname為一個目錄,那么為該目錄更名。如果newname已存在,則它必須是一個目錄,而且該目錄應當是空目錄(空目錄指的是該目錄中只有. 和.. 項)。如果newname存在(而且是一個空目錄),則先將其刪除,然後將oldname更名為newname。另外,當為一個目錄更名時,newname不能包含oldname作為其路徑前綴。例如,不能將/usr更名為/usr/foo/testdir,因為老名字( /usr/foo)是新名字的路徑前綴,因而不能將其刪除。

(3) 作為一個特例,如果oldname和newname引用同一檔案,則函式不做任何更改而成功返回。

返回值 執行成功則返回0,失敗返回-1,錯誤原因存於errno

範例

#include

int main(int argc,char **argv)

{

if(argc < 3)

{

printf("Usage: %s old_name new_name\n",argv[0]);

return -1;

}

printf("%s => %s\n", argv[1], argv[2]);

if(rename(argv[1], argv[2]) < 0 )

printf("error!\n");

else

printf("ok!\n");

return 0;

}

dos命令

簡介

功能:重命名檔案或資料夾

用法:rename 完整路徑檔案名稱(資料夾名) 新檔案名稱(新資料夾名)

ren 完整路徑檔案名稱(資料夾名) 新檔案名稱(新資料夾名)

套用舉例

例子:

如想修改D糟下的檔案1.txt為2.txt可以在cmd中執行命令

ren d:\1.txt 2.txt

如想修改D糟下的資料夾old為資料夾new可以在cmd中執行命令

ren d:\old new

Linux命令

linux中rename和mv都可以對檔案重命名,在此對rename命令和mv命令在重命名檔案方面做一個比較。

可以看到mv命令確實有重命名的功能,但是實際套用中,它只能對單個檔案重命名,命令如下:

mv [path/]oldfilename [path/]newfilename "mv命令只能對單個檔案重命名",這實就是mv命令和rename命令的在重命名方面的根本區別。

再來說rename命令,rename命令是專用於檔案重命名的,而且根據其後的例子可以看出,rename除了給單個檔案重命名,還可以批量檔案重命名。

Linux的rename 命令有兩個版本,一個是C語言版本的,一個是Perl語言版本的,早期的Linux發行版基本上使用的是C語言版本的,現在已經很難見到C語言版本的了,由於歷史原因,在Perl語言大紅大紫的時候,Linux的工具開發者們信仰Perl能取代C,所以大部分工具原來是C版本的都被Perl改寫了,因為Perl版本的支持正則處理,所以功能更加強大,已經不再需要C語言版本的了。

1.區分rename命令的版本

輸入man rename 看到第一行是

RENAME(1) Linux Programmer’s Manual RENAME(1)

那么 這個就是C語言版本的。

而如果出現的是:

RENAME(1) Perl Programmers Reference Guide RENAME(1)

這個就是Perl版本的了!

2.兩個版本的語法基本差異

C語言的參數格式

按照man上面的註解,rename的語法格式是: rename from to file

這個命令有 三個參數,分別是from : 修改什麼名字,to:改成什麼名字,file 需要修改的檔案是哪些。

perl版本的參數格式

rename perlexpr files

注意,perl版本的rename只有 兩個參數,第一個參數為perl正則表達式,第二個參數為所要處理的檔案

3.C語言版本的rename

值得注意一點的是,

C語言版本的rename命令是帶3個參數而不是很多人認為的2個參數。

上面的例子中給出了兩種檔案批量重命名的用法,而實際上,rename結合通配符使用,它的功能比上面的例子所顯示的更強大。基本的通配符有以下幾個:

? 可替代單個字元

* 可替代多個字元

[charset] 可替代charset集中的任意單個字元

rename把檔案名稱中的第一個參數字元串用第二個參數替換,只替換符合第三個參數模式的檔案名稱。

下面以例子加以說明:

如資料夾中有這些檔案foo1, ..., foo9, foo10, ..., foo278,如果使用

rename foo foo0 foo?

則它只會把foo1到foo9的檔案重命名為foo01到foo09,因為?通配符只能替代單個字元,所以被重命名的檔案只是有4個字元長度名稱的檔案,檔案名稱中的foo被替換為foo0。

再繼續使用

rename foo foo0 foo??

則資料夾中的foo01到foo99的所有檔案都被重命名為foo001到foo099,而foo100及其以後的檔案名稱都不變,因為通配符?的使用,所以只重命名5個字元長度名稱的檔案,檔案名稱中的foo被替換為foo0。

如果再繼續使用

rename foo foo0 foo*

則foo001到foo278的所有檔案都被重命名為foo0001到foo0278,因為通配符*可替代多個字元,所以,所有以foo開頭的檔案都被重命名了,檔案名稱中的foo被替換為foo0。

我們再來看通配符[charset]的用法,還是繼續在上面所說的資料夾中,執行如下命令

rename foo0 foo foo0[2]*

則從foo0200到foo0278的所有檔案都被重命名為foo200到foo278,檔案名稱中的foo0被替換為foo。

4.perl語言版本的rename

帶有Perl的好處是,你可以使用正則表達式來完成很奇特的功能。

man rename的幫助示例:

1) 有一批檔案,以.bak結尾,現在想把這些.bak 統統去掉。

rename 's/\.bak$//' *.bak

這個命令很簡單,因為我還沒有系統學習過perl,我不知道perl里替換字元串是不是這么乾的,但sed是這么乾的,所以如果你有sed或者tr基礎,很容易明白,這個替換和sed里的正則語法是一模一樣的。

2) 把所有檔案名稱內含有大小字母的,修改為小寫字母。

rename 'y/A-Z/a-z/' *

依然和sed的替換語法一樣,不用多解釋,如果看不懂的話,可以系統學習一下sed先。

還有幾個比較實用的例子:

1) 批量去掉檔案名稱里的空格

Linux檔案名稱本來是不支持空格的,不知道什麼時候允許了,當然,在命令行調用檔案的時候,空格是很有問題滴,比如你 原來可以直接 mv oldfile newfile 但有空格就不行了 , 得加雙引號:mv "oldfile" "newfile" 或者用反斜槓轉移 \[] ,這樣還好,但如果你直接把含有空格的圖片名引入Latex文檔,Latex生成pdf的時候會直接列印出檔案名稱,之前這個問題苦惱了我很久,我生成的pdf怎么老是出現檔案名稱呢?後來才發現原來是檔案名稱內含有空格的問題!windows系統下生成的檔案名稱是天生含有空格的,雖然很討厭,但有些惠普掃瞄器生成的圖片默認就加入了空格,沒有辦法,只好去掉他,在系統研究rename命令前,我是用mv 去除空格的。

網上流程的兩個去空格的版本:

1) tr 版:

find . -type f -name "* *" -print |

while read name; do

na=$(echo $name | tr ' ' '_')

if [[ $name != $na ]]; then

mv "$name" $na

fi

done

這個版本以前我一直用的,不知道哪個網上搜刮來的,當時還沒有系統的學習過tr/sed/awk命令。

註解一下,很好理解,find . type f -name "* *" -print 這一句是查找當前目錄下所有類型為普通檔案的 並且名字之中含有空格的檔案,並列印出來,其實find默認就是列印的 這個-print 多餘了,然後 通過管道傳輸給while 循環讀取,檔案名稱放到name 變數里,用tr 命令替換空格為下劃線。 下面判斷如果執行後的名稱不相同,使用mv 命令重命名。但這個if判斷可有可無,因為find已經查詢了所有檔案名稱中含有空格的,那么經過tr 命令後,$na變數肯定不等於$name 變數的。

所以這段代碼可以簡化:

find . -type f -name "* *" |

while read name; do

na=$(echo $name | tr ' ' '_')

mv "$name" "$na"

done

tr 可以看著是sed 的一個精簡版本,tr 用下劃線來替換空格。

還有一個 是sed 版本實現:

for f in *;do mv "$f" `echo "$f" | sed 's/[ ]\+/_/g' `; done

這裡的sed表達式還可以這樣寫:

sed 's/[[:space:]]\+/_/g'

不過記住,sed里的出現一次或多次的加號是需要添加反斜槓的。即:\+,這樣就可以了。

好了,這兩種辦法都太他媽羅嗦了,看看rename實現吧:

rename 's/[ ]+/_/g' *

OK就這么簡單。

方括弧內的空格可以用[:space:]代替,

即可以寫成's/[[:space:]]+/_/g'

這裡注意,rename 採用的是標準perl正則語法,所以無須將加號轉變為反斜槓加號

即+ 不能修改為\+,否則替換失敗。

還有幾個好玩的例子:

比如統一在檔案頭部添加上hello

rename 's/^/hello/' *

統一把.html擴展名修改為.htm

rename 's/.html$/.htm/' *

統一在尾部追加.zip後綴:

rename 's/$/.zip/' *

統一去掉.zip後綴:

rename 's/.zip$//' *

規則化數字編號名,比如1.jpg, 2.jpg ..... 100.jpg , 現在要使檔案名稱全部三位即1.jpg .... 001.jpg

運行兩次命令:

rename 's/^/00/' [0-9].jpg # 這一步把1.jpg ..... 9.jpg 變幻為001.jpg .... 009.jpg

rename 's/^/0/' [0-9][0-9].jpg # 這一步把10.jpg ..... 99.jpg 變幻為010.jpg ..... 090.jpg

Ok ,rename就研究了這么多,暫時不知道如何在rename中引入動態變數,比如$i++

我測試過i=0; rename -n "s/^.*$/$((++i))/" * 執行後i被自增了1,並非想我想像中那樣,可以在每操作一個檔案自增一,猜想可能是因為rename批量實現的,導致++i只計算一次!

-n 用來測試rename過程,並不直接運行,可以查看測試效果後,然後再運行。

好了,再次說明一下,你在使用的時候一定要確認一下你語言的版本……

相關詞條

相關搜尋

熱門詞條

聯絡我們