Linux批量重命名 rename & mv [轉]


剛學習linux的時候,對文件重命名首先想到的就是rename命令,但是按照 在windows下對文件重命名的方式試了N多次都沒有反應,在網上一搜索,發現很多人都對rename命令知之甚少,甚至有一部分人說linux下沒有 rename命令,建議大家用mv命令。鑑於此,於是man rename一下,好好的研究了一下它的用法 ,在此對rename命令和mv命令在重命名文件方面做一個比較,有不足之處,希望各位博友指正!

首先來說一下mv命令,在man mv中我們可以看到對於mv命令的介紹是這樣的:

mv -move(rename) files

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

mv [path/]oldfilename [path/]newfilename

“mv命令只能對單個文件重命名”,這實就是mv命令和rename命令的在重命名方面的根本區別。

再來說rename命令,在man rename的說明如下:

NAME

rename -Rename files

SYNOPSIS

rename from to file....

DESCRIPTION

rename will rename the specified files by replacing the first occurrence of from in their name by to.

For example, given the files foo1, ..., foo9, foo10, ..., foo278, the commands

rename foo foo0 foo?

rename foo foo0 foo??

will turn them into foo001, ..., foo009, foo010, ..., foo278.

And

rename .htm .html *.htm

will fix the extension of your html files.

可以看出rename命令是專用於文件重命名的,而且根據其後的例子可以看出,rename除了給單個文件重命名,還可以批量文件重命名。同時,值得注意一點的是,rename命令是帶3個參數而不是很多人認爲的2個參數。

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

? 可替代單個字符

* 可替代多個字符

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

下面以例子加以說明:

如文件夾中有這些文件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。

在使用中,三種通配符可以一起結合使用,關於具體的其它用法就只有自己不斷的摸索了

 

或者用編程語言

Linux批量重命名文件會涉及到改變一個字母、改變一些相連字母、改變某些位置的字母、在最前面加上某些字母、或者改變字母的大小寫。完成這裏五個方法基本上就會解決了Linux批量重命名的工作。

1、我想把它們的名字的第一個1個字母變爲"q",其它的不變

[root@pps mailqueue]# for i in `ls`; do mv -f $i `echo $i | sed 's/^./q/'`; done

或者寫個腳本,顯得更加清晰:

  1. for file in `ls`
  2. do
  3.   newfile =`echo $i | sed 's/^./q/'`
  4.  mv $file $newfile
  5. done


2、修改前面5個字母爲zhaozh

[root@pps mailqueue]# for i in `ls`; do mv -f $i `echo $i | sed 's/^...../zhaozh/'`; done

3、修改後面5個字母爲snail

[root@pps mailqueue]# for i in `ls`; do mv -f $i `echo $i | sed 's/.....$/snail/'`; done

4、在前面添加 _hoho_

[root@pps mailqueue]# for i in `ls`; do mv -f $i `echo "_hoho_"$i`; done

5、所有的小寫字母變大寫字母

[root@pps mailqueue]# for i in `ls`; do mv -f $i `echo $i | tr a-z A-Z`; done

  

 

=================================================

Linux rename命令 批量重命名

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

 


如何區分系統裏的rename命令是哪個版本的?

輸入 man rename 看到第一行是

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

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

而如果出現的是:
RENAME(1)              Perl Programmers Reference Guide              RENAME(1)

這個就是Perl版本的了!


兩個版本的語法差異:

C語言的,按照man上面的註解,
rename的語法格式是:

rename
 fromtofile

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

用法示例:
比如,有一批文件,都是以 log開頭的, log001.txt,  log002.txt ....... 一直到 log100.txt
現在想要把這批文件的log全部替換爲 history 
rename 
 log history log*

這句命令的意思很明白了,把 以 log開頭的所有文件中的 log字符替換爲 history
這樣替換後的文件是: history001.txt,  history002.txt ..... 一直到 history100.txt

rename C語言版本的另一個man示例是把後綴名批量修改,
比如我們要將所有 jpeg的後綴名圖片文件修改爲 jpg文件。

rename
 .jpeg.jpg*.jpeg

這樣,所有以 .jpeg擴展的後綴名全部被修改爲 .jpg

現在總結一下rename C語言版本所能實現的功能: 批量修改文件名,結果是每個文件會被用相同的一個字符串替換掉!也就是說,無法實現諸如循環 然後按編號重命名!



2, Perl 版本的批量重命名,帶有Perl的好處是,你可以使用正則表達式來完成很奇特的功能。

perl 版本的參數格式:

rename 
 perlexprfiles

注意,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過程,並不直接運行,可以查看測試效果後,然後再運行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章