2008年9月7日 星期日

svn update script

因為最近在使用svn,
每次有新的進度之後,就要開始看哪一些需要更新,
有時候編譯出來的檔案實在有夠多~

不可能一個指令一個指令下去打,很浪費時間~
但是,又要更新,這是一定要做的,所以,今天就研究了一下,
看能不能寫一個script來幫助我update這一些資料

所以,研究了awk這一個小工具,真的很好用,可以用來分析文件中的資料~
研究了六個小時左右終於寫出來了~這一個東西以後真的可以幫我省六個小時回來嗎?
[2008/11/20補充]
在這幾個月用下來,我覺得真的還不錯用~


以下是我寫出來的script,要放在svn的目錄下才可以使用
update.sh

#!/bin/bash

#把svn status 的結果送到temp檔
svn status > temp

#抓行數
total_line=`awk '{print NR}' temp|tail -n1`

#迴圈
for ((current_line=1;current_line<=$total_line;current_line=current_line+1))
do
  awk -v current=$current_line -v total=$total_line '{
    if ($1=="?" && current==NR && $2!="temp")
    {
      printf("========================================\n");
      printf("%s\n",$0);
      printf("Do you want to add(a) or delete(d):");
      "read yn && echo $yn" | getline yn;
      if (yn == "a")
      {
        cmd = "svn add "$2;
        print(cmd); // debug用
        system(cmd);
      }
      else if (yn == "d")
      {
        cmd = "svn delete --force "$2;
        print(cmd); // debug用
        system(cmd);
      }
    }
    else if ($1=="!" && current==NR && $2!="temp")
    {
      printf("========================================\n");
      printf("%s\n",$0);
      printf("Do you want to revert(r) or delete(d):");
      "read yn && echo $yn" | getline yn;
      if (yn == "r")
      {
        cmd = "svn revert "$2;
        print(cmd); // debug用
        system(cmd);
      }
      else if (yn == "d")
      {
        cmd = "svn delete "$2;
        print(cmd); // debug用
        system(cmd);
      }
    }
  }' temp
done
#刪除暫存檔temp
echo "========================================"
rm -rfv temp

NR是表示目前是第幾行,current和current_line記錄目前是第幾行;total和total_line是記錄temp一共有幾行。


這裡要說明一下,我的effort。
一開始我是打算全部都用awk來完成我的目標,awk是可以分析檔案的內容作適當的動作。
但是呢?在svn的顯示要更新的列表我目前只有兩項要注意的「!」、「?」
「?」:就是表示server沒有檔案,client有檔案。在這一個情況下我有兩個可能的動作要做;
一、這一個資料是我剛剛新增的,所以,我應該要打svn add path指令
二、這一個資料是Makefile幫我建出來了,我不想要它,我要打svn delete --force path的指令
「!」:這一個表示server有檔案,但是,client端確沒有檔案。在這一個情況下我有兩個可能的動作;
一、這一個本來就是我想要刪掉,或是我打Makefile打令把它刪掉的,要打svn delete --force path指令
二、這一個就是不小心被我刪掉了資料,我必需要還原它,要打svn revert path指令還原它

這裡遇到一些問題,
一、awk沒有提供function讓使用著在程式執行時輸入資料,這樣就不能跟使用者互動了,還好,awk有提供一個指令command | getline var透過shell的command傳值給var變數。因此,input的部分我必需透過shell的read指令來幫助我~
二、非常意外的,在同一個awk中,command | getline var竟然只能執行一次,而之後若要重覆執行,就會讀取之前輸入的資料,因此,我必需透過shell script讓每分析新的一行,我必需重新執行awk,而每一次執行awk,我必需只讀取我要分析的那一行,不然,又是由第一行開始,那第一行就會執行command | getline var,那我就前功盡棄啦~
三、我必需要知道這一個文件有幾行~不然,我怎麼去設定迴圈哩~
四、shell的變數與awk裡面的變數是不相同的,我必需透過-v參數把total_line與current_line的值傳送進去~
五、等我分析完之後,我還必在awk中透過shell打上我要打的svn指令,還好,awk提供了system(command)的這一個function,可以透過它傳送給shell指令


如何在awk使用傳送要給shell的指令
例:

awk -F: '/正規表示法/
{
  cmd="命令字串";
  print cmd;
  system(cmd)
}' file


取得文件行數
總結了一下有五種方法:
現在有一個a文件,共有55行
第一種:

[root@host ~]# awk '{print NR}' a|tail -n1


第二種:

[root@host ~]# awk 'END{print NR}' a


第三種:

[root@host ~]# grep -n "" a|awk -F: '{print '}|tail -n1

第四種:

[root@host ~]# sed -n '$=' a

第五種:

[root@host ~]# wc -l a|awk '{print }'

第六種:

[root@host ~]# cat a |wc -l


[2009.06.14 補充]
若要一次新增許多資料的話,而且分散在各各不同的資料夾,則有三個方法,第一個是一個一個加,第二個是使用上面的script,第三個是使用下面的指令
$ svn status | awk '{print $2}' | xargs svn add
而以上的指令使用條件是必需要是所有svn state所出來的檔案都是要新增的

參考資料:
好用的 awk 命令
AWK 中如何利用系統資源
怎樣取得文件行數

沒有留言: