2012-06-19 44 views
1

我想遞歸地將一個篩選器(例如sed -e 's/OLD/NEW/g')應用於svn屬性值。通過篩選器命令編輯svn屬性

首先,對一個目標,我可以做下列之一:

  1. svn propget --strict PROPNAME TARGET | sed -e 's/OLD/NEW/g' | svn propset PROPNAME --file=- TARGET
  2. svn propset PROPNAME --file=<(svn propget --strict PROPNAME TARGET | sed -e 's/OLD/NEW/g') TARGET
  3. SVN_EDITOR="sed -i -e 's/OLD/NEW/g'" svn propedit PROPNAME TARGET
  4. svn propedit --editor-cmd "sed -i -e 's/OLD/NEW/g'" PROPNAME TARGET

哪一個會bes T'

我不喜歡關於1或2的是,即使svn propget ... | sed ...管道失敗,仍然執行svn propset,可能在一個空的stdin上重置屬性。

在另一方面,我不喜歡約3或4是整個過濾命令行應該被引用並製成一個串,這有時使得報價和參數擴展棘手。並注意選項-i - 過濾命令應該採取一個文件參數和到位,這意味着這些方法不能適用於不提供這種就地編輯功能的命令,如tr甚至awk編輯。

有沒有更好的選擇,或者其中的一種可能的改進?

第二個,我該如何遞歸地做 - 即在給定TARGET下每個具有指定屬性PROPNAME的目標上?我不能只添加-Rsvn propget,因爲它會將所有內容拼接成一個文本流,並且svn propedit甚至沒有-R。看來,我必須做一些事情,如:

svn proplist -R --only-with PROPNAME TARGET | while read target 
do 
    # do one of the above on "$target" 
done 

svn proplist沒有這樣的東西叫做--only-with,我不能簡單地分析其產量和搶只有具有財產這些目標的名字。

有什麼好的方法可以做到嗎?

回答

1

svn propget -R的輸出不容易分析,但svn propget -v -R的輸出是,所以我決定運行一次並解析其輸出。

首先,我嘗試了進程替換>(...),但如this thread中所述,我無法執行或等待終止這樣的子進程,因此輸出消息很亂,儘管它確實有效。因此,在the same thread回答,我用協進程:

#!/bin/bash 
set -o errexit -o pipefail 

if [ $# -le 2 ]; then 
    echo "usage: $0 PROPNAME TARGET COMMAND [ARGS...]" >&2 
    exit 1 
fi 
PROPNAME=$1; shift 
TARGET=$1; shift 
COMMAND=$1; shift 

cleanup_and_wait() { 
    if [[ ${COPROC[1]} =~ ^[0-9]+$ ]]; then 
     eval "exec ${COPROC[1]}<&-" 
     wait $COPROC_PID 
    fi 
} 

unset curr_target 
unset prev_line 
while IFS= read -r line; do 
    case "$line" in 
    " "*) 
     line=${line:4} 
     if declare -p prev_line >/dev/null 2>&1; then 
      echo "$prev_line" >&${COPROC[1]} 
     fi 
     prev_line=$line 
     ;; 
    " "*) 
     line=${line:2} 
     if [ "$line" != "$PROPNAME" ]; then 
      echo "Unexpected property: $line" >&2 
     fi 
     cleanup_and_wait 
     coproc { "$COMMAND" "[email protected]" | svn propset "$PROPNAME" --file=- "$curr_target"; } >&2 
     unset prev_line 
     ;; 
    "Properties on '"*"':") 
     line=${line%"':"} 
     line=${line#"Properties on '"} 
     curr_target=$line 
     ;; 
    esac 
done < <(svn propget --verbose --recursive "$PROPNAME" "$TARGET") 
cleanup_and_wait 

我不喜歡一個次要的事情是,即使在給定的過濾器不改變屬性值,svn propset仍在執行並打印property 'PROPNAME' set on 'TARGET';只有那些屬性值實際發生變化的目標纔會看到消息。