Perl經典代碼之rename
Larry Wall的rename腳本, 隻用了個位行數的代碼就構造出一個功能超強的批量檔案重命名工具:
注釋:
1. # touch rename.perl //建立一個檔案:rename.perl , 内容如下。
2. # chmod +x rename.perl
3. # cp rename.perl /bin/
4. # rename.perl 's/gongxu/leibie/g' * //将目錄中所有檔案名中的 gongxu 替換為 leibie。
#!/usr/bin/perl -w
# rename - Larry's filename fixer
#用法: Perl表達式 [要處理的檔案名]
$op = shift or die "Usage: rename expr [files]\n";
#如果沒有給出要處理的檔案名則從标準輸入讀入
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
$was = $_;
eval $op; #對待處理的檔案名($_)執行使用者輸入的Perl表達式$op
die $@ if $@; #退出 , 如果eval出錯
rename($was,$_) unless $was eq $_;
}
rename腳本的經典執行個體示範:
% rename.perl 's/\.orig$//' *.orig #移除檔案末尾的.orig
% rename.perl "tr/A-Z/a-z/ unless /^Make/" * #所有非Make打頭的檔案名大寫轉為小寫
% rename.perl '$_ .= ".bad"' *.f #每個*.f檔案後面追加一個.bad
% rename.perl 'print "$_: "; s/foo/bar/ if <STDIN> =~ /^y/i' * #回顯每個待處理的檔案名, 等待輸入, 如果使用者輸入以y或Y打頭, 把檔案名中的foo替換成bar
% find /tmp -name "*~" -print | rename.perl 's/^(.+)~$/.#$1/' #把 /tmp目錄裡面每個檔案名末尾有~的檔案名改成以.#開頭
http://www.linuxidc.com/Linux/2011-01/31594.htm
Linux的 rename 指令有兩個版本,一個是C語言版本的,一個是Perl語言版本的,早期的Linux發行版基本上使用的是C語言版本的,現在已經很難見到C語言版本的了,因為Perl版本的支援正則處理,是以功能更加強大,已經不再需要C語言版本的了。
如何區分系統裡的rename指令是哪個版本的?
輸入 man rename 看到第一行是
RENAME(1) Linux Programmer’s Manual RENAME(1)
那麼 這個就是C語言版本的。
而如果出現的是:
RENAME(1) Perl Programmers Reference Guide RENAME(1)
這個就是Perl版本的了!
兩個版本的文法差異:
1.C語言的,按照man上面的注解,
rename的文法格式是:
rename from to file
這個指令有三個參數,分别是 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 perlexpr files
注意,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 去除空格的。
rename 's/[ ]+/_/g' *
方括号内的空格可以用 [:space:]代替,
即可以寫成 's/[[:space:]]+/_/g'
這裡注意,rename 采用的是标準perl正則文法,是以無須将 加号轉變為反斜杠加号
即 + 不能修改為 \+,否則替換失敗。
還有幾個好玩的例子:
比如統一在檔案頭部添加上 hello
rename 's/^/hello/' *
統一把.html擴充名修改為 .htm
rename 's/.html$/.htm/' *
統一在尾部追加 .zip字尾:
rename 's/$/.zip/' *
統一去掉.zip字尾:
rename 's/.zip$//' *
批量更改檔案名 rename
通過 man rename 指令可以得知,rename 指令其實是一個 Perl 腳本指令,
它專用于批量地給多檔案重命名(rename multiple files)。
指令格式:
rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]
perlexpr 是一種 Perl 腳本格式的正規表達式。
參數:
-v, --verbose
Verbose: print names of files successfully renamed.
詳細模式:列印成功更改的檔案名清單
-n, --no-act
No Action: show what files would have been renamed.
測試模式:并不真正的執行指令,而隻是顯示哪些檔案名應該怎麼進行
更改,用于測試模式。
-f, --force
Force: overwrite existing files.
強制模式:在更改檔案名,如果更改後的檔案已經存在時覆寫已經存在
的檔案。
完。