ファイル名パターンまたはディレクトリのbash補完


12

bash完了スクリプトを設定しようとしていて、問題が発生しています。

リストされた補完が特定の拡張子に一致するファイル、またはディレクトリ(その拡張子のファイルを含む場合と含まない場合がある)のいずれかになるように設定したいと思います。

私が抱えている問題は、ファイルディレクトリを含めるための補完を取得できる唯一の方法は、のようなものを使用することですが-o plusdirs -f -X '!*.txt'、bashにディレクトリの1つを補完させると、スペースではなくスペースが最後に追加されるだけですスラッシュ。

_xyz()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  local prev=${COMP_WORDS[COMP_CWORD-1]}

  #COMPREPLY=( $( compgen -f -X '!*.txt' -- $cur ) )
  #COMPREPLY=( $( compgen -f -G '*.txt' -- $cur ) )
  #COMPREPLY=( $( compgen -o filenames -f -X '!*.txt' -- $cur ) )
  #COMPREPLY=( $( compgen -o dirnames  -f -X '!*.txt' -- $cur ) )
  COMPREPLY=( $( compgen -o plusdirs  -f -X '!*.txt' -- $cur ) )
  return 0
}

complete -F _xyz xyz

コメントアウトされた行もすべて試しましたが、ディレクトリを展開することさえしません。

テストのために、1つの.txtファイルと1つのディレクトリ「dir」を含むディレクトリでこれを実行しました(その中に.txtファイルがありますが、それはまだ重要ではありません)。xyz <TAB>この関数を入力すると、ディレクトリと.txtファイルが一覧表示されますが、入力xyz d<TAB>すると展開されますxyz dir(「dir」の後にスペースが追加されます)。

回答:


10

/ etc / bash_completionの関数_cd()を見ると、末尾のスラッシュ自体が追加され、cdのオプションでその完全なものが呼び出されることがわかります。-o nospace

xyzについても同じことができますが、見つかった一致がディレクトリ(存在する場合はスラッシュ)またはファイル(存在する場合はスペースを追加)であるかどうかを個別に確認する必要があります。これは、見つかったすべての一致を処理するためにforループで実行する必要があります。

また、スペースを含むパスを適切に処理するには、内部ファイル区切り文字を改行のみに設定し、スペースをエスケープする必要があります。IFS=$'\n'と組み合わせて使用すると、printf %qほぼすべての文字で補完が機能します。1後続スペースから逃げないように特別な注意が必要です。

以下が機能するはずです。

_xyz ()
{
    local IFS=$'\n'
    local LASTCHAR=' '

    COMPREPLY=($(compgen -o plusdirs -f -X '!*.txt' \
        -- "${COMP_WORDS[COMP_CWORD]}"))

    if [ ${#COMPREPLY[@]} = 1 ]; then
        [ -d "$COMPREPLY" ] && LASTCHAR=/
        COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR")
    else
        for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
            [ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
        done
    fi

    return 0
}

complete -o nospace -F _xyz xyz

1改行文字は、内部ファイル区切り文字であるため、ここでは明らかな例外です。


これはうまく機能します(残念ながら、組み込まれていません)。ありがとう!
ロブI

1
「$ {COMP_WORDS [COMP_CWORD]}」の代わりに「$ 2」を使用しない理由は何ですか?
エドワードフォーク

3

私はこのシンプルなソリューションがそれで機能すると思う:

  1. で終わるディレクトリとファイルに一致します .txt
  2. ファイル名のスペースを処理します
  3. フォルダー補完の最後にスラッシュを追加します。末尾にスペースはありません。
  4. ファイル補完の一致の最後にスペースを追加します

キーは-o filenames完了に合格していました。これは、RHEL 5.3上のGNU bash 3.2.25およびosx上のGNU bash 4.3.18でテストされました。

_xyz()
{
  local cur=${COMP_WORDS[COMP_CWORD]}

  local IFS=$'\n'
  COMPREPLY=( $( compgen -o plusdirs  -f -X '!*.txt' -- $cur ) )
}

complete -o filenames -F _xyz xyz

はい、それはうまくいくようです。もっとシンプルに、重要な議論をキャッチしてくれてありがとう!
ロブI 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.