File::Copy復制文件
File::Copy模塊提供了copy函數和cp函數來復制文件,它們參數上完全一致,但行為上稍有區別。
用法大致如下:
use File::Copy qw(copy cp);
copy("sourcefile","destinationfile") or die "Copy failed: $!";
copy("Copy.pm",\*STDOUT);
- 兩個參數都可以是文件或文件句柄或者文件句柄通配,第一個參數指定源,第二個參數指定目標
- 如果第一個參數是文件句柄,那么將直接從文件句柄來讀取數據,如果這個參數是文件,那么將打開這個文件來讀取數據
- 第二個參數是數據的寫入目標
- 如果目標文件不存在,但父目錄存在,則創建該目標文件,但如果父目錄也不存在,則報錯
- 如果目標文件存在,則覆蓋該目標文件,不會給出任何提示
- 如果目標是一個已存在的目錄,且源不是一個文件句柄,則拷貝到目標目錄中,如果源是一個文件句柄,將報錯
- 源和目標不能是同一文件
- 因為是拷貝操作,所以可以跨文件系統拷貝
- 第三個可選參數用於設置拷貝時的緩沖大小。對於文件來說,一般緩沖大小是整個文件(但最大2MB),對於不關聯實體文件的文件句柄(如套接字文件句柄),默認為1K大小
- cp可以替換copy。它們的參數模式完全一致,但cp會保留源文件的屬性,而copy則是采用目標文件的默認屬性。此外,cp在遇到權限錯誤的時候返回0,而不管文件是否成功拷貝
- 強烈建議:如果可以,都使用文件名而不是文件句柄。如果要使用文件句柄,則采用binmode模式的文件句柄,以免丟失某些數據
- File::Copy模塊無法操作目錄,所以copy無法復制目錄
例如,現在/mnt/g下創建一個文件t1.py。然后執行如下內容的perl程序:它將拷貝root下的t.py,然后再拷貝覆蓋到已存在的t1.py。
use File::Copy qw(copy cp);
copy "/root/t.py","/mnt/g/" or die "Can't copy file1: $!";
cp qw(/mnt/g/t.py /mnt/g/t1.py) or die "Can't copy file2: $!";
重命名/移動文件
rename函數可以重命名文件,也可以移動文件到其它目錄。功能類似於unix下的mv命令。
rename old_name,new_name;
rename old_name => new_name; # 列表環境下,逗號可用胖箭頭替換
但需要注意,rename函數無法跨文件系統移動文件,因為它的底層僅僅只是重命名,修改文件inode中的數據。跨文件系統移動文件,實際上是復制文件再刪除源文件,它會導致inode號碼改變,rename的本質是基於inode的,無法實現這樣的功能。
rename "test2.log","test222.log"
or die "Can't rename file1: $!";
rename "test222.log","/tmp/test223.log"
or die "Can't rename file2: $!";
rename "/tmp/test223.log","/boot/test223.log" # 本行將報錯
or die "Can't rename file3: $!";
File::Copy模塊提供了move函數,它可以跨文件系統移動文件。用法大致如下:
use File::Copy qw(move mv);
move("/dev1/sourcefile","/dev2/destinationfile");
mv("/dev1/sourcefile","/dev2/destinationfile");
mv("/dev1/sourcefile" => "/dev2/destinationfile");
- File::Copy模塊無法操作目錄,所以move無法重命名或移動目錄
- move有兩個參數,第一個是源,第二個是目標
- 如果目標是個已存在的目錄,而源是個非目錄,則源將被移動到目標目錄內
- 如果可以,move在文件系統底層只是簡單地重命名文件。否則(例如跨文件系統),將copy源文件到目標,然后刪除源文件。如果這個copy+delete的過程中失敗,則在目標路徑下會遺留一個可能還未拷貝完成的副本
- move可以使用mv替代
其實,可以采用shell交互的方式來取巧重命名:
rename(old,new) or system("mv",old,new);
遞歸復制/移動File::Copy::Recursive
具體內容暫缺,可看官方手冊:File::Copy::Recursive