2017-04-11 7 views
0

私はこのコードをbashスクリプトで使用しています。ソースフォルダを複数の宛先に転送するのに使用します。tee引数として任意の数のプロセス置換を生成します。

cd /Volumes/ ; tar cf - SOURCE/ | tee \ 
>(cd /Volumes/dest1 ; tar xf -) \ 
>(cd /Volumes/dest2 ; tar xf -) \ 
> /dev/null 

このコマンドはうまくいきます。スクリプトの冒頭に送り先を設定したいと思います。したがって、目的地の数は変わる可能性があります。

たとえば目的地は、VARまたは配列になります

destinationList=/Volumes/dest1 /Volumes/dest2 
cd /Volumes/Untitled/ ; tar cf - SOURCE/ | tee \ 
# for item in destinationList 
# do 
#  add this code ">(cd $item ; tar xf -)" 
# done 
> /dev/null 

はそれを行うための良い方法はありますか?

+2

私は」 dはむしろこれを「Tee引数として任意の数のプロセス置換を生成する」と題してください - 余分な引数を 'tee'に渡すのは簡単です。これらの議論をプロセスの代用にするのは難しいです。 –

+0

私はタイトルを編集しました –

+3

ところで、 'cd" $ 1 "の代わりに' cd "$ 1" && tar'に注意してください; 'tar'は私の答えでは' cd 'が失敗し、現在のディレクトリがあなたの意図した目的地以外のどこかにある場合に 'tar'を実行したくないということです。 (これは実際にhttp://shellcheck.net/がキャッチするバグです)。 –

答えて

5

evalは、非常に注意深く使用する必要がありますが、これは簡単なオプションの1つです。

unpackInDestinations() { 
    local dest currArg='' evalStr='' 
    for dest; do 
    printf -v currArg '>(cd %q && exec tar xf -)' "$dest" 
    evalStr+=" $currArg" 
    done 
    eval "tee $evalStr >/dev/null" 
} 

tar cf - SOURCE/ | unpackInDestinations /Volumes/dest{1,2} 

少ない効率的に(しかし、おそらく、コードのセキュリティなどの多くの驚きを監査しようとしている原因と誰もがなし)、1はまた、再帰関数記述することができます。

unpackInDestinations() { 
    local dest 
    if (($# == 0)); then 
    cat >/dev/null 
    elif (($# == 1)); then 
    cd "$1" && tar xf - 
    else 
    dest=$1; shift 
    tee >(cd "$dest" && exec tar xf -) | unpackInDestinations "[email protected]" 
    fi 
} 

teeの数をこれは引数の数によって変化するので、手書きコードや実質的には同等のものよりも効率が悪いです。


あなただけのbashの新しいバージョンをサポートする必要がある場合は、両方の世界の最高を提供できる利用可能ないくつかの追加の魔法があります(下記少なくとも 4.1が必要です):

unpackInDestinations() { 
    local -a dest_fds=() args=() 
    local arg fd_num retval 

    # open a file descriptor for each argument 
    for arg; do 
    exec {fd_num}> >(cd "$arg" && exec tar xf -) 
    dest_fds+=("$fd_num") 
    args+=("/dev/fd/$fd_num") 
    done 

    tee "${args[@]}" >/dev/null; retval=$? 

    # close the FDs 
    for fd_num in "${dest_fds[@]}"; do 
    exec {fd_num}>&- 
    done 

    # and return the exit status we got from tee 
    return "$retval" 
} 
+0

名前付きファイル記述子について私は知らなかった。私はそれが必要であることを知ったときにそれについて覚えています。変数はローカルで使用できますか(上記のコードにはないようです)? – Fred

+0

@Fred、いいコール - はい、私はその地方にフラグを立てたはずです。 –

関連する問題