2017-01-21 13 views
2

私はリストから1つのオプションを選択する必要があるbashスクリプトを書いています。オプションのリストは実際には、ディレクトリ内のファイルのベース名(パスと拡張子なし)と、シンボリックリンクを除外する必要があるという追加の要件のリストです。bashでselect構造体のリストを処理する

私はもともとのサブディレクトリを選択するためのものですthis other questionに投稿された1つのライナー愛して:私は、ファイルのbasenameを取得するには、そのファイルがシンボリックリンクではない場合はどのように確認する方法を知っている

printf "Please select folder:\n" 
select d in */; do test -n "$d" && break; echo ">>> Invalid Selection"; done 
cd "$d" && pwd 

をそれはファイルごとです。ただし、select構成はファイルのリストを管理します。どういうふうにbasenameコマンドとチェックを接続して、select構成要素のすべての要素にチェックを入れて、selectに到着する前にリストをフィルタリングして処理することができますか?

答えて

2

)あなたのファイル名が心配はほとんどありませんこれは、埋め込まれていない改行を持っていないと仮定すると:あなたのプラットフォームとfind実装に依存し、これは合理化することができることを

#!/usr/bin/env bash 

# Collect the sorted names of all regular files in the current directory 
# in array ${files[@]}. 
IFS=$'\n' read -d '' -ra files < <(find . -maxdepth 1 -type f | cut -d/ -f2 | sort) 
# Bash 4.x would allow the simpler: 
# readarray -t files < ... 

select f in "${files[@]}"; do 
    [[ -n "$f" ]] && break # Valid selection made, exit the menu. 
    echo ">>> Invalid Selection" >&2 
done 

# "$f" contains the selected file. 

注意を。

-type fは、通常のファイルのみと一致し、自動的にシンボリックリンクを除外します。

+0

はい、可能な限り下位互換性があり、Bash 4.xに依存したくないと思います。実際、ソリューションがBourneシェルと互換性があっても、私はそれを好むでしょう。 – cesss

+1

@cesss、aside:Bourne( '^'をパイプ文字として使用できる1970年代のシェル)、あるいはPOSIX sh(90年代初期のbash、ksh 、ダッシュなどはスーパーセットの実装です)? –

+0

@cesss:ソリューションBash 3.xと互換性があります。あなたが本当に移植可能なソリューションを望むなら、あなたの質問に 'bash'というタグを付けないでください。 'select'コマンドはPOSIXシェル仕様の一部ではなく、どちらも配列変数ではないことに注意してください。 – mklement0

1

(bashのソリューションを要求して明示的にあなたの質問にもかかわらず)bashismsを回避次善のアプローチ、しかもシェルに組み込まれていない任意のツールに応じて回避:

特に
#!/bin/sh 
set --      ## clear our argument list to reuse it 

printf "Please select folder:\n" 
for d in */; do    ## iterate only over directories 
    [ -L "${d}%/" ] && continue ## skip to next item if we have a link 
    d=${d%/}; d=${d##*/}  ## alternative to basename using only parameter expansion 
    set -- "[email protected]" "$d"   ## append our result to "[email protected]" 
done 
select d in "[email protected]"; do   ## ...and then expand "[email protected]" to select over 
    cd "$d" && pwd 
done 

  • "[email protected]"は、ベースラインのPOSIX shで利用できることが保証されている唯一の配列です。各スタックフレームは異なる引数リストを提供するので、関数内にこのコードをカプセル化することによって、グローバル"[email protected]"を上書きすることを避けることができます。
  • O(n)set -- "[email protected]" "$value"ではなく、array+=("$value")でO(1)操作として配列の追加を行うことができます(現在のリストを展開する必要があるため、既存の引数リストlengnh)。
+1

しかし、 'select'文はPOSIXシェル仕様の一部ではないので、この場合、Bashismsには無駄な行為は避けられませんか? – mklement0

+1

@ mklement0、* shrug *。 specは明示的に 'select'のための準備をしますが、それはそれを必要としません。確かにそれをサポートする非bashシェル(少なくとも初期kshに戻る)があります。 –

+1

はい、 'ksh'と' zsh'も 'select'をサポートしますが、' dash'はそうではありません。私が[spec。](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html)で見つかったのは次のとおりです。 "次の単語は、いくつかの実装で予約語として認識されるかもしれません。 '' [''、 '] ''、 '' select' ") – mklement0

関連する問題