ファイル数が多い特定のディレクトリに対して、Bashでタブの完成を無効にしますか?

ファイル数が多い特定のディレクトリに対して、Bashでタブの完成を無効にしますか?

私は大量のファイルを扱っており、そのファイルをディレクトリに保存しています。そのディレクトリに入り、誤ってTab2回押すたびにパターンに一致するファイルが表示されるのに時間がかかりません(おそらく1分以上)、この動作は本当に面倒です。

たとえば、私のディレクトリ構造は次のようになります。

my-project/
├── docs/
├── data/        <---- contains around 200k files.
└── analyser/

data/私はまだ完成を好むので、ディレクトリでのみこの機能を無効にする方法はありますか?たとえば、タイムアウトを5秒に設定するか、特定のディレクトリで完了したスクリプトを自動的に閉じますか?

ベストアンサー1

完璧ではありませんが、bashの完成はかなりトリッキーなことです...

最も簡単な方法はコマンドごとに行うことですが、これはFIGNOREあなたができるよりも少し柔軟です。

 complete -f -X "/myproject/data/*" vi

これは、オートコンプリート機能がviファイルに対して完了し、-Xフィルタに一致するパターンを削除するように指示します。欠点は、スキーマが標準化されず、../data変更が一致しないことです。

次善策はおそらくユーザー定義PROMPT_COMMAND関数です。

# associative arrays of non-autocomplete directories
declare -A noacdirs=([/myproject/data]=1 )

function _myprompt {
    [[ -n "${noacdirs[$PWD]}" ]] && {
       echo autocomplete off
       bind 'set disable-completion on'
    } || {
       echo autocomplete on
       bind 'set disable-completion off'
    }
} 

PROMPT_COMMAND=_myprompt

これ完了を無効にする(完全に)ディレクトリにあるとき、しかし、そのディレクトリのファイルだけでなく、すべてのパスに対して無効になります。

定義されたパスに対してこれを選択的に無効にする方が一般的ですが、唯一の方法は基本的な補完機能(bash-4.1以降complete -D)を使用することであり、多くの混乱を引き起こします。

これしなければならないあなたには効果がありますが、可能予期しない副作用があります(例:予想完了が変わります)。

declare -A noacdirs=([/myproject/data]=1 )

_xcomplete() {
    local cur=${COMP_WORDS[COMP_CWORD]} # the current token

    name=$(readlink -f "${cur:-./}")  # poor man's path canonify
    dirname=$(dirname "$name/.")

    [[ -n "${noacdirs[$dirname]}" ]] && {
        COMPREPLY=( "" )   # dummy to prevent completion
        return
    }
    # let default kick in
    COMPREPLY=()
}

complete -o bashdefault -o default -F _xcomplete vi

これは完了のために機能し、vi必要に応じて他のコマンドを追加できます。パスまたは作業ディレクトリに関係なく、指定したディレクトリのファイルの完了を停止する必要があります。

私は一般的なアプローチは、complete -D各コマンドが発生するたびに完成機能を動的に追加することだと思います。追加する必要がありますcomplete -E(入力バッファが空の場合は完全なコマンド名)。


修正するPROMPT_COMMAND以下は、理解してハッキングしやすい、完全な機能ソリューションのハイブリッドバージョンです。

declare -A noacdirs=([/myproject/data]=1 [/project2/bigdata]=1)

_xcomplete() {
    local cmd=${COMP_WORDS[0]}
    local cur=${COMP_WORDS[COMP_CWORD]} # the current token

    [[ -z "$cur" && -n "$nocomplete" ]] && {
        printf "\n(restricted completion for $cmd in $nocomplete)\n"  
        printf "$PS2 $COMP_LINE"
        COMPREPLY=( "" )   # dummy to prevent completion
        return
    }
    COMPREPLY=()       # let default kick in
}

function _myprompt {
    nocomplete=
    # uncomment next line for hard-coded list of directories
    [[ -n "${noacdirs[$PWD]}" ]] && nocomplete=$PWD
    # uncomment next line for per-directory ".noautocomplete"
    # [[ -f ./.noautocomplete ]] && nocomplete=$PWD
    # uncomment next line for size-based guessing of large directories
    # [[ $(stat -c %s .) -gt 512*1024 ]] && nocomplete=$PWD
} 

PROMPT_COMMAND=_myprompt
complete -o bashdefault -o default -F _xcomplete vi cp scp diff

nocompleteこのプロンプト機能は、設定されたディレクトリの1つを入力するときに変数を設定します。変更された完了アクションは、変数が空でない場合にのみ適用されます。そしてこれにより、空の文字列で完成しようとした場合にのみ部分名を完成させることができます(-z "$cur"完全に完了しないようにするには、条件を削除してください)。自動操作のためにこれらの2行をコメントアウトしてくださいprintf

他のオプションには、必要に応じてディレクトリに配置できるディレクトリ固有の.noautocompleteフラグファイルと、GNUを使用してディレクトリサイズを推測する機能が含まれます。これら 3 つのオプションの一部または全部を使用できます。touchstat

stat方法ただ推測です。、報告されたディレクトリサイズはその内容に応じて増加します。これは「ハイウォーターマーク」であり、通常は管理者の介入なしにファイルが削除されたときに減りません。潜在的に大きなディレクトリの実際の内容を決定するよりも安価です。各ファイルの正確な動作と増分は、基本ファイルシステムによって異なります。私はこれが少なくともLinux ext2/3/4システムでは信頼できる指標だと思います。 )

空の完成が返されても、bashは余分なスペースを追加します(これは行末の完成でのみ発生します)。これが発生しないように-o nospaceコマンドを追加できます。complete

残りのマイナーな問題は、カーソルをマークアップの先頭に戻し、Tabを押すと基本的な完成が再開されることです。機能だと思います;-)

(または、過度のエンジニアリングが好きなら自由に使用できますが、${COMP_LINE:$COMP_POINT-1:1}バックアップしてコマンドの途中で完了しようとすると、bash自体が完了変数を安定して設定しないことがわかりました。)

おすすめ記事