2016-03-21 6 views
1

私はほとんどのバージョン番号のディレクトリを持っていますが、別の特定のバージョンの直前にバージョンソートされたものを特定しようとしています。bashでソートされたリストから選択

ここでの背景は、これらのバージョン番号がWebコンテンツ用のgitタグから派生したもので、サイトの仮想ホストのバージョン番号public_htmlディレクトリをバージョン管理されたディレクトリにシンボリックリンクすることです。

それはこのようなものになります。

drwxr-xr-x 8 graham www 17 Oct 17 2013 v2.0.10 
drwxr-xr-x 8 graham www 17 Oct 17 2013 v2.0.11 
drwxrwxr-x 8 graham www 17 Aug 29 2013 v2.0.8 
drwxr-xr-x 8 brian www 17 Oct 17 2013 v2.0.9 
... 
drwxr-xr-x 9 graham www 21 Aug 5 2015 v4.19.0 
drwxr-xr-x 10 graham www 19 Dec 17 2014 v4.2.0 
drwxr-xr-x 9 brian www 21 Aug 10 2015 v4.20.0 
drwxr-xr-x 9 brian www 21 Aug 10 2015 v4.20.0-fail 
drwxr-xr-x 9 graham www 21 Aug 11 2015 v4.20.1 
... 
drwxr-xr-x 9 graham www 19 Mar 14 11:00 v4.35.0 
drwxr-xr-x 9 graham www 19 Mar 14 13:28 v4.36.0 
drwxr-xr-x 9 graham www 19 Mar 16 10:58 v4.36.1 
lrwxr-xr-x 1 graham www 11 Mar 16 11:13 public_html -> v4.36.1 

シンボリックリンクは常に最新のバージョンを指してされないことを(例えば、我々は変更をバックアウトしていた場合)。私の目標は、public_htmlが指し示すディレクトリよりも前にソートされたバージョンである適切な名前のディレクトリ(つまり、*-failなどをスキップします)を見つけることです。

statコマンドは次のようにうまく動作しますので、私は、FreeBSDの中だ:

read target <<<"$(stat -f'%Y' "${base}/public_html")" 

あなたは、Linuxであれば、私はあなたがこのようなものと同じ効果を得ることができ集める:

target="$(stat -c '%N' "${base}/public_html")" 
target="${target#* -> ?}"; target="${target%?}" 

ここからは、どのようにバージョン番号を収集するのか分かりません。私はFreeBSDにいるので、私のsortコマンドには-Vオプションがありません。私は2つの方法を試みました。

最初のディレクトリの内容にwhileループを処理する:

shopt -s extglob 
while read this; do 
    [[ "$this" = "$target" ]] && break 
    previous="$this" 
done < $(ls -1d v+([0-9]).+([0-9]).+([0-9]) | sort -n -t . -k1,1 -k2,2 -k3,3) 

第二の代わりに配列を解析し、かなり類似している:

shopt -s extglob 
a=($(ls -1d v+([0-9]).+([0-9]).+([0-9]) | sort -n -t . -k1,1 -k2,2 -k3,3)) 
for ((n=0; n<${#a[@]}; n++)); do 
    [[ "${a[$n]}" = "$target" ]] && break 
    previous="${a[$n]}" 
done 

これらの両方が落ちる場合がありますsortで、最初のフィールドはソートされていないようです。私はそれが数字ではないからだと思う(最初は "v"で、 "。"で区切られている)。どういうわけか、複数の区切り文字を指定する方法がありますか、それ以外の場合は「無視」しますか?v

これを処理するには、移植性の低いオプションの外部sortコマンドを使用するよりも良い方法がありますか?たぶん内部の何かをbashにする?

ありがとうございました。

答えて

0
おそらく

ない完全ソリューションが、あなたは次のように逃げることができるかもしれません:

ls -1d v+([0-9]).+([0-9]).+([0-9]) | sort -t . -k1,1 -k2,2n -k3,3n 

ここでの違いは、数値フィールドの-nは、第2及び第3のフィールドにのみ適用されていることですので、最初のフィールドでアルファベット順にソートします。

これはv9.x.xからv10.x.xへのジャンプのお手伝いをしませんが、あなたは3年弱でv4v2から行ってきたとして、おそらくそれは「十分」です。ALSO

  • あなたは二段階でこれを実行する可能性があります。最初の段階では、major=$(ls -1d v[0-9]* | tail -1); major=${major%%.*}"のような最新のメジャーバージョン番号が決定され、その後のソートはa=$(ls ${major}.+([0-9]).+([0-9]))に基づいています。次に、数値フィールドだけで安全に並べ替えることができます。
  • a bash implementation of qsortが、完全にbash内部にあるものを作るために適応できるかもしれません。それはあなたの配列で動作するようにいくつかのハッキングを必要とします。
0

あなたはサブフィールドによってソート数値、アルファ接頭辞を分離し、そして私はV10を追加した。*それは将来の証拠だことを確認するために戻って

$ ls -1 v* | sed 's/^v/v./' | sort -t. -k2,2n -k3,3n -k4n | sed 's/^v\./v/' 

v2.0.8 
v2.0.9 
v2.0.10 
v2.0.11 
v4.2.0 
v4.19.0 
v4.20.0 
v4.20.0-fail 
v4.20.1 
v4.26.1 
v4.35.0 
v4.36.0 
v10.0.1 

ノートをマージすることができます。

+0

?これはバージョンオプションがないための回避策です。 – karakfa

+0

申し訳ありませんが、私の間違い。今日の午後は読むことができません。 –

0

readlinkを除く)この純粋なバッシュ解決策ではなく、ソートの線形検索を行います。

あなたが使用し `-V`オプションを参照してくださいでした
VERSION_RX='^v([0-9][0-9]*)\.([0-9][0-9]*)\.([0-9][0-9]*)$' 

target=$(readlink "$base/public_html") 

# target == v1.22.333 -> target_key == 000000001_000000022_000000333 
[[ $target =~ $VERSION_RX ]] || exit 1 
printf -v target_key '%09d_%09d_%09d' \ 
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" 

pred_dir= 
pred_key= 

for path in "$base"/v*.*.* ; do 
    dir=${path##*/} 
    [[ $dir == "$target" ]] && continue 
    [[ $dir =~ $VERSION_RX ]] || continue 
    printf -v key '%09d_%09d_%09d' \ 
     "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}" 

    [[ $key > $target_key ]] && continue 

    if [[ -z $pred_key || $key > $pred_key ]] ; then 
     pred_dir=$dir 
     pred_key=$key 
    fi 
done 

echo "$pred_dir" 
関連する問題