[Perl]如何複製檔案及目錄

use File::Copy;
copy('file1.txt','file2.txt') or die "can't copy: $!\n";

複製目錄

sub copy_dir{
  my $source = $_[0];
  my $target = $_[1];
  use File::Copy;
  opendir(DIR,$source);
  while(my $filename = readdir(DIR)){
    if(-f "$source/$filename")){
      copy("$source/$filename","$target/$filename") or die "can't copy: $!\n";
    }
  }
  close(DIR);
}

參考網頁

  • File::Copy - Copy files or filehandles
  • [轉載][JavaScript]你所想像不到的 JavaScript

    轉載自: 愛德華日誌


    這不是一篇教你如何在網頁中應用 JavaScript 的教材。這是一篇讓你明瞭看似簡單的 JavaScript,其實其核心語法功能強大。我將在這篇文章中說明 JavaScript 物件導向的特性,並說明如何透過這些特性,達到傳統程式語言 (C++/Java) 所難以完成的功能。

    Everything is Object in JavaScript

    開宗明義:在 JavaScript 中任何東西都是物件:變數是物件、函式是物件,常數也是物件。證明方式:

    alert (typeof('abc'));
    alert (typeof(123));
    var ary = [123, "abc"];
    alert (typeof(ary));

    上面的 typeof 會顯示物件資料型態。得到結果分別是 string, number, object。

    Create Objects in JavaScript

    既然任何東西都是物件,那建立物件的方法就多了。直接看個例子:

    var main = new Object;     // 建立新物件
    main.x = 123; // 設定物件成員變數(屬性)之一
    main["y"] = "XYZ"; // 設定物件成員變數(屬性)之二
    alert(main["x"]); // 取得物件屬性並輸出
    alert(main.y);

    可以看到在 JavaScript 中,main.x 與 main["x"] 這兩種語法是通用的。其實在其他語言中,這兩種表示法的語意並不相同。我稍後再作說明。

    List All Members in an Object

    這是 JavaScript 的必殺技,使用 JavaScript 的人務必要學會這個技巧。底下函式可以傳回一個物件的所有成員的字串表達式,包括物件中的屬性及方法。在物件導向程式設計中,這種技術叫 reflection。

    function listMember(main) {
      var s = "";
      for( key in main )  // 使用 in 運算子列舉所有成員
      s += key + ": " + main[key] + "\n";
      return s;
    }

    範例碼中的 key 會對應到物件中的屬性名稱,如 “x” 或 “y”,而 main[key] 則對應到屬性值。

    說這項技巧是必殺技的原因是,你可以透過這項技巧,將物件封裝的黑箱打開來,看看裡面藏有什麼東西。我常用這項技巧來看看 IE 與 Mozilla 的 Dom 物件模型有何不同。試試看下面呼叫範例,就可以知道這項技巧的強大了:

    var ary = [123, "abc"];
    alert (listMember(ary));
    alert (listMember(document.location));

    Construct Object with Initial Value

    要在建立物件的同時指定物件初始值,必須先透過 function 建立一個「原型物件」(或稱為 constructor),再透過 new 運算子建立新物件。例如以下程式碼會建立一個二維陣列的原型,再產生一個新的二維物件。

    function Array2DVar(x,y) {  // 定義二維陣列原型
      this.length = x;
      this.x = x;  // x 維度長度
      this.y = y;  // y 維度長度
      for(var i = 0; i < this.length; i++)  // 初始各元素值為 null
      this[i] = new Array(y);  // this 代表物件本身
    }
    
    var a2dv = new Array2DVar(10, 10);  // 建立新的 10*10 的二維陣列
    a2dv[1][3] = "ABC";  // 設定二維陣列元素值
    a2dv[2][6] = "XYZ";
    a2dv[9][9] = 1000;
    
    alert( a2dv[1][3]);  // 取得二維陣列元素值,並顯示出來
    alert( a2dv[2][6]);
    alert( a2dv[9][9]);

    Initial Array Object

    在 JavaScript 中陣列也是物件 (其實近代多數語言中陣列也都是物件,只有像 C 或 Assembly 這類古老的語言才不把陣列看成物件),因此也可以用 constructor 的語法來建構。當然 JavaScript 還提供了 [] 語法,以更方便建構陣列,範例如下:

    a = new Array("abc", "xyz", 1000); // constructor 語法,或
    a = ["abc", "xyz", 1000]; // 陣列標準語法

    陣列的元素可以是簡單的資料、其他物件,或是函數。舉個例子來在陣列裡面放函式:

    b = [ // 使用函式作為陣列元素
      function () { alert("這個好玩!") },
      function () { alert("再按一次離開!") },
      function () { alert("再來一次!") },
      function () { alert("最後一次!") }
    ];
    
    for (var i = 0; i < b.length ; i++)
    b[i]();

    最後一個 for 迴圈是個有趣的應用。由於 b 陣列中現在存放的所有元素都是函式,因此我們可以對 b 的每個元素進行呼叫。

    Object as Association Array

    關聯陣列 (Assocation Array) 又稱作 Map 或 Dictionary,是一種物件容器,其中可以放置許多的 key-value pair,以存取子物件。在JavaScript 中,物件本身就可以作為關連陣列。以關聯陣列的方式初始化物件的範例如下:

    obj1 = {"a" : "Athens" , "b" : "Belgrade", "c" : "Cairo"};
    alert(obj1["a"]);  // 顯示 Athens
    obj2 = {
      name: "Edward",
      showName: function() { alert(this.name); }  // 使用函式作為物件屬性
    }
    obj2.showName();  // 顯示 Edward
    obj2.age = 23;  // 屬性可以動態加入

    其 中 obj1 儲存了三個子元素,其鍵 (key) 為 “a”, “b” 與 “c”,而值 (value) 為 “Athens”, “Belgrade” 與 “Cairo”。obj2 中 showName 鍵所對應的值為 function,因此 obj2.showName() 即為函式呼叫。

    Object as Return Value

    雖然 Javascript 的函式只能傳回一個變數,但您卻可以將傳回值設定為物件,達到傳回 1個以上變數值的效果

    function a () {
      return [32, 17];
    }
    b = a();
    alert( b ); // 或
    alert(a());
    function pixel () {
      return {"x": 32, "y":17};
    }
    point = pixel ();
    alert (point.x + "\n" + point.y);  // 或
    alert (pixel().x + "\n" + pixel().y);

    Delegation Function Object

    函式也是物件,只是其中包含的是程式的邏輯。這項特性可拿來作為委任式的程式設計,亦即使用委任函式當作另一函式的參數:

    function doloop(begin, end, func) {  // 這個函式是個 iterator
      for (var i = begin; i < end; i++) {
        func(i);
      }
    }
    function func1(i) {  // 印出 ** n **
      document.writeln("** " + i + " **<br>");
    }
    doloop(1, 10, func1);  // 印出 10 行 ** n **
    doloop(20, 29,
      function(i) {  // 印出 10 行 ## n ##
        document.writeln("## " + i + " ##<br>");
      }
    );

    Object = Properties + Behaviors

    古有明訓:程式 = 資料結構 + 演算法。而物件是建構程式的基本單位,自然的具有相同的性質。物件除了有屬性 (property),也可具有操作 (behavior),也就是函式。

    假如我們要使用一維陣列來模擬二維陣列,那麼就無法使用 ary[x][y] 這種表示法來設定或取得陣列成員。不過我可以定義一個 set 方法來設定成員變數,而以 get 方法來取得成員變數值。原型函式定義如下:

    function Array2D(x,y){  // 以一維陣列模擬二維陣列的原型物件
      this.length = x * y;  // 陣列總長
      this.x = x;  // x 維度長度
      this.y = y;  // y 維度長度
      for(var i = 0; i < this.length; i++)  // 初始各元素值為 null
        this[i] = null;
      this.get = function(x,y){  // 成員函式:取得陣列第 [x,y]個元素值
        return this[x*this.x + y];
      }
      this.set = function(x,y,value){  // 成員函式:設定陣列第 [x,y] 個元素值
        this[x*this.x + y] = value;
      }
    }

    我們接著來使用它:

    var a2d = new Array2D(10, 10);  // 建立新的「二維」陣列
    
    a2d.set(1, 3, "ABC");  // 設定「二維」陣列元素值
    a2d.set(2, 6, "XYZ");
    a2d.set(9, 9, 1000);
    
    alert( a2d.get(1,3) );  // 取得「二維」陣列元素值,並顯示出來
    alert( a2d.get(2,6) );
    alert( a2d.get(9,9) );

    Member Function Outside of Constructor

    我們也可以將物件成員函式寫於原型物件之外。以下的 Array2D 物件與上一個範例中的 Array2D 物件有相同的作用,只不過這次是寫在原型物件之外。

    function Array2D(x,y){  // 以一維陣列模擬二維陣列的原型物件
      this.length = x * y;  // 陣列總長
      this.x = x;  // x 維度長度
      this.y = y;  // y 維度長度
      for(var i = 0; i < this.length; i++)  // 初始各元素值為 null
        this[i] = null;
      this.get = Array2DGet;  // 用這種方式把成員函式掛進來
      this.set = Array2DSet;
    }
    
    function Array2DGet(x,y){  // 成員函式:取得陣列第 [x,y] 個元素值
      return this[x*this.x + y];
    }
    
    function Array2DSet(x,y,value){  // 成員函式:設定陣列第 [x,y] 個元素值
      this[x*this.x + y] = value;
    }

    Dynamic Object Function

    這裡說明如何為一個已定義物件,動態的加上其他操作的方法。

    如果一物件已定義完成,而您也使用它來建立了新的物件,這時候您想為原型物件增加新的操作 (而不修改原型物件的原始碼),讓所有該物件的複本都能使用該操作,該如何達成呢?方法是使用物件的 prototype 屬性。以下這個例子,為 Array 這類 Object 在執行期加入一個 max 方法,以取得陣列元素之最大值 (修改自微軟 jscript.chm之範例):

    function array_max(){  // 定義求取 Array 最大值之函式
      var i, max = this[0];
      for (i = 1; i < this.length; i++){
      if (max < this[i])
        max = this[i];
      }
      return max;
    }
    Array.prototype.max = array_max;  // 在 Array 原型中加入 max 函式

    上面的程式碼,首先建立一個 array_max 方法,以求取陣列之最大元素。接著將這個方法設定給 Array 原型物件。

    var x = new Array(1, 2, 3, 4, 5, 6);  // 透過 Array 建構子建立一陣列,想求取 x 中某一元素之最大值
    var y = x.max( );  // 取得 x 之最大元素

    Dynamic Mix in

    假如物件 dynamic 有 method1, method2 兩個函式;而另一物件 main 有 methodA 及 methodB 兩個函式。現在我想把 dynamic 的所有特性 (feature) 匯入到 main 中,我們可以在 main 中加上一個 imports 函式:

    function main(){  // main 之建構子
      // ...
      this.imports =
        function (object) {
          if( typeof object == "object")
            for( value in object )
              this[value] = object[value];
        }
      // ...
    }
    obj = new main();
    main.imports(new dynamic());  // 匯入 dynamic 物件之所有功能

    這個 imports 函式可以動態的為 main 加上另一物件的所有操作。這種 Mix in 的功能可是 C++/Java 的 static type 語言所望塵莫及的。

    IP 位址區段計算程式 *

    檔案下載

    有時候 MIS 需要計算區段 IP 的啟始位置和終點 IP,使用這個程式,只需要填入目標 IP,就會幫您算出:

    • IP 數
    • 開始的 IP(Network IP)
    • 結束的 IP(Brocase IP)
    • 網路遮罩(Subnet Mask)

    而且不用安裝就可以使用了。

    .htaccess 簡易的網頁帳號認證

    .htaccess 讓你不用寫程式,就可以用最簡單的方式做出「網頁登入」的功能,限制哪些用戶能進到網頁的某一層目錄。

    建立用戶驗證資料

    建立用戶驗證檔

    建立用戶驗證檔,並新增一組帳號及密碼:

    htpasswd -c /path/to/.htusers UserName1

    這裡所產生的 .htusers 是一個文字檔,裡面會有用戶名稱及編碼過的密碼。第一次建立檔案時,必須加 -c 參數。同時,請找一個安全的地方放置 .htusers 這個檔案,所謂的「安全」是指至少不要在公開網頁可以被下載到的路徑,例如放在 public_html 的上一層。

    繼續增加第二組帳號及密碼到驗證檔時,就不用加 -c 參數:

    htpasswd /path/to/.htusers UserName2

    建立群組資料檔

    如果用戶比較多,你可能會想要用群組的方式來做管理。群組資料檔的目的是要將多個用戶設為一個群組,請新增或編輯 /path/to/.htgroups,依需求增加類似如下的設定:

    Group1:UserName1 UserName2

    代表 Group1 包含 UserName1UserName2 這兩個用戶。

    驗證登入

    在欲執行用戶驗證的網頁目錄下,建立一個 .htaccess 檔案,驗證的方式可針對用戶或群組,差別在於 require 這個參數。

    針對用戶:

    AuthName "Restricted Area" # 名稱必須用英文
    AuthType Basic
    AuthUserFile /path/to/.htusers
    require user UserName1 # 僅針對特定用戶,以空白分隔多個用戶

    上述的最後一行是只有 UserName1 允許進入,你也可以改成:

    require valid-user # 針對全部用戶

    表示針對 .htusers 裡的所有用戶。

    針對群組:

    AuthName "Restricted Area" # 名稱必須用英文
    AuthType Basic
    AuthUserFile /path/to/.htusers
    AuthGroupFile /path/to/.htgroups
    require group Group1 # 僅針對特定群組的用戶,以空白分隔多個群組

    表示針對 .htgroups 裡,歸屬於 Group1 下的用戶。

    針對特定檔案:

    若你只想針對特定檔案做保護,那可以與 <Files>~</Files> 一起使用:

    <Files FileName>
         require valid-user
    </Files>

    <Files>~</Files> 一次只能填寫一個檔案,但支援正規表示式。以下是使用正規表示式限制圖檔存取的範例:

    <Files ~ "\.(gif|jpe?g|png)$">
         require valid-user
    </Files>

    或是:

    <FilesMatch "\.(gif|jpe?g|png)$">
         require valid-user
    </FilesMatch>

    設定好之後,當用戶要存取該目錄 (或檔案),就會跳出叫你登入的對話框:


    另外,你也可以在網址中直接輸入你的帳號、密碼,格式:

     http://UserName:Password@www.example.com/directory/

    問題排除

    如果在設定 htaccess 認證方式之後,在進入網頁時,仍然沒有跳出驗證的對話框,則請編輯 /etc/httpd/conf/httpd.conf,搜尋相關的「AllowOverride」設定,改成:

    AllowOverride All

    安全性問題

    雖然用戶儲存在 Server 端的密碼有經過加密,但因為是採用 Basic 方式驗證,當要存取網頁時,用戶輸入的帳號與密碼僅是以 Base64 編碼,包裹在 Headers 裡進行傳輸,有機會被竊聽之後解碼、盜用! 網站必須導入 SSL 才能完全在傳輸的過程中加密。

    參考網頁

    Who Is Connected 1.6.1 - 讓駭客現形

    檔案下載

    你是否覺得電腦的執行速度突然變慢?是否想知道有沒有人在存取你電腦上的資料?是否覺得網路速度越變越慢?是否擔心你的電腦被植入了木馬程式?Who Is Connected 這套軟體就可以幫你解決這些疑問。雖然這套軟體全部是英文界面,但還是畫面簡單,不須太高深的網路知識,很適合一般家用電腦使用者。它的好處是,當你發現有可疑連線入侵時,可以馬上阻斷連線,並列入為禁止連線的黑名單。你也可在斷線時,先發出 Message 詢問對方到底有何用意。
    Read more

    [轉載]Unicode 脫逸序列轉換

    轉載自: IT Inside


    這裡提供一段程式碼,可以透過 JavaScript 將文字轉換為 Unicode 脫逸序列。這段程式碼,不論是對網頁開發人員,還是對 java resource bundle 的翻譯人員,都有很大的方便性。使用時只要將底下的程式碼複製起來,以 html 副檔名儲存,就可以用 browser 執行了。

    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
    <script language=javascript>
    <!--
    function StringToUniCode(source) {
      sret = "";
      // Unicode 跳脫序列之格式為 \u00ff
      for(var i=0; i < source.length; i++) {
       var num = new Number( source.charCodeAt(i));
       sret += "\\u" + num.toString(16);
      }
      return sret;
    }
    function convert(){
      document.forms.content.result.value = StringToUniCode(document.forms.content.source.value);
    }
    //-->
    </script>
    將文字轉成 Unicode 跳脫序列
    <form name=content>
    來源:<input type=TEXT name=source size=40 value="常用連絡人"><br />
    結果:<input type=TEXT name=result size=40><br />
    <input type=button value=轉換 onclick="convert()">
    </form>

    UltraFXP 1.07 - 高效能的 FTP 程式

    檔案下載

    這是一個高效能的 FTP 程式,也是我認為最強的 FTP 程式,因為產品版權的爭議,UltraFXP 的 1.07 版,改為 Freeware 發行。不過,現在已經被買走了,改名叫 FTPRush,恢復成 ShareWare 繼續發行。

    Read more

    在 Linux 上建立虛擬主機最快速的方法 *

    本篇的目的,是說明如何使用最簡單的方式在你的網頁伺服器 (Apache) 上新增一個虛擬主機 (Virtual Host),讓你只要建一個目錄,或新增一個本機用戶,就可以建立虛擬主機,並且可自動分割 Log 檔 (以下之設定牽涉到 Apache 及 DNS 的觀念,最好也有自行架設 DNS 服務)。
    Read more

    Redhat Linux 9.0 中文手冊 *

    檔案下載

    內含 Redhat Linux 9.0 的安裝手冊、使用手冊及用戶自訂手冊,HTML 格式。

    你也可以到這裡讀取:

    相關網頁

    HTTP 回應的代碼含義

    當我們在瀏覽網頁的時候,經常會看到諸如 500 錯誤之類的訊息,這些錯誤代碼所代表的含義作為網站的開發人員,應該必須瞭解的。

    HTTP 的回應代碼是三位數字,其中第一個數字定義了代碼的類別:

    範圍 類別 含義
    100~199 訊息 請求被接收,正在處理
    200~299 成功 動作被成功接收、理解和接受
    300~399 重新導向 必須採取其他動作才能完成請求
    400~499 用戶錯誤 請求包含不良語法或無法完成
    500~599 伺服器錯誤 伺服器無法處理的請求

    其中較常見的 HTTP 回應代碼有:

    • 200: 請求成功
    • 400: 語法錯誤
    • 401: 未經授權
    • 403: 禁止訪問
    • 404: 請求的網頁不存在
    • 500: 伺服器錯誤

    Read more

    return top