原文地址:http://www.javashuo.com/article/p-toquyrsg-cw.htmlcss
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語言版本的。【我查看系統上應該就是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*【C的用法~】
這句命令的意思很明白了,把 以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過程,並不直接運行,能夠查看測試效果後,而後再運行。
好了,再次說明一下,你在使用的時候必定要確認一下你語言的版本,個人是C語言版本~
RENAME(1) Linux Programmer’s Manual RENAME(1)
功能:
rename from to file...
用法:
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.
下面來看一個例子:html
最後再來個實際應用當中的問題,先看下如下的圖~linux
看到了吧,咱們想把那個圖片文件名中的ad字母換成big【注意:拷貝一份,不能直接替換】,那麼想一想該怎麼作呢,對了,就是用rename~
cd /data/openshop_1028/IMG_SERVER/sources/goods/
find ./ -name "*_ad.jpg" -exec cp "{}" {}.1 \;
find ./ -name "*_ad.jpg.1" -exec renamead.jpg.1 big.jpg {} \;
假如要是可以直接替換的話,那就一條命令了:
cd /data/openshop_1028/IMG_SERVER/sources/goods/
find ./ -name "*_ad.jpg" -exec rename ad big {} \;
能夠看如下的測試~正則表達式