2011-03-15 85 views
-1

我正在學習和擴展由他人編寫的Perl腳本。它有一條線:Perl文件名更改

@pub=`ls $sourceDir | grep '\.htm' | grep -v Default | head -550`; 
foreach (@pub) { 

    my $docName = $_; 
    chomp($docName); 
    $docName =~ s/\.htm$//g; 
    ............} 

我知道它首先使用UNIX命令取出所有htm文件,然後擺脫文件擴展名。

現在我需要做一件事,這也是非常重要的。也就是說,我需要通過用下劃線替換空格來更改存儲的實際文件的文件名。我被困在這裏,因爲我不確定我是否應該遵循他的代碼風格,通過使用UNIX來實現此目標,還是應該在Perl中執行此操作?重點是我需要修改磁盤上的實際文件,而不是用來保存文件名的字符串。

謝謝。

回答

2

使用File::Copy將文件移動到其新名稱的速度會更快,而不是使用此方法分叉新的進程,產生新的shell等等,它會佔用更多的內存並且比在perl內執行更慢本身。

編輯..你可以擺脫所有的反引號BS的,太像這樣

my @files = grep {!/Default/} glob "$sourcedir/*.html"; 
+0

由於源和目標是在同一個目錄下,你可以使用'rename'。有關詳細信息,請參閱'perldoc -f rename'。 – shawnhcorey 2011-03-15 19:08:53

+0

我用move(),但總是失敗,你認爲這是一個權限問題? – Kevin 2011-03-15 20:43:55

+0

如果腳本的euid/egid與文件的所有權不匹配,那麼很可能是權限問題。當它失敗時它給出了什麼錯誤?嘗試添加'或死'$!\ n「'到你正在使用移動的那一行。 – BadFileMagic 2011-03-15 21:39:56

3

像這樣的東西應該幫助(未測試)

use File::Basename; 
use File::Spec; 
use File::Copy; 
use strict; 

my @files = grep { ! /Default/ } glob("$sourceDir/*.htm"); 
# I didn't implement the "head -550" part as I don't understand the point. 
# But you can easily do it using `splice()` function. 

foreach my $file (@files) { 
    next unless (-f $file); # Don't rename directories! 
    my $dirname = dirname($file); # file's directory, so we rename only the file itself. 
    my $file_name = basename($file); # File name fore renaming. 
    my $new_file_name = $file_name; 
    $new_file_name =~ s/ /_/g; # replace all spaces with underscores 
    rename($file, File::Spec->catfile($dirname, $new_file_name)) 
     or die $!; # Error handling - what if we couldn't rename? 
} 
+0

更好地使用y/\ s/_/s而不是s// _/g?保羅 – pavel 2011-03-15 19:03:00

+0

我確實把你的代碼。但是我得到了錯誤:「全局符號」@pub「需要顯式包名」,你可以幫忙嗎? – Kevin 2011-03-15 19:09:51

+0

所以你沒有使用代碼作爲DVK提供...沒有你的當前代碼我猜我的@pub ...應該做的伎倆... – pavel 2011-03-15 19:24:59