web-dev-qa-db-ja.com

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

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」の後にスペースが付きます)。

13
Rob I

/ etc/bash_completionの関数_cd()を見ると、末尾にスラッシュ自体が追加されていることがわかります。 completeは、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 改行文字は内部のファイル区切り文字であるため、ここでは明らかな例外です。

10
Dennis

この単純な解決策は、次の点で機能すると思います。

  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
3
Chad Skeeters