多数のファイルを含むディレクトリのBashでタブ補完を無効にしますか?


19

私はディレクトリに保管している多数のファイルで作業しています。そのディレクトリに移動して誤ってTab2回押すたびに、パターンに一致するファイルを表示するのに時間がかかりすぎます(1分以上かかることがあります)。

たとえば、私のディレクトリ構造は次のとおりです。

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

私はまだ完了が大好きなので、data/ディレクトリでのみこの機能を無効にする方法はありますか?5秒間のタイムアウトの設定、または特定のディレクトリ内での完了を自動的にオフにするスクリプトのようなものですか?


これでzshに切り替えますか?(私がチェックしていない、それはbashで可能だ場合、私は、私はそれがzshの中で可能です知っているかわからないが、それは簡単ではないかもしれません。)
ジル「SO-停止されて悪」

回答:


9

これは完璧ではありませんが、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"完全に完了しないように条件を削除します)。printfサイレント操作のために2 行をコメント化します。

他のオプションには、必要に応じてディレクトリ内で使用.noautocompleteできるディレクトリごとのフラグファイルが含まtouchれます。GNUを使用したディレクトリサイズの推測stat。これら3つのオプションのいずれかまたはすべてを使用できます。

stat方法は推測過ぎず、報告されたディレクトリサイズはその内容とともに増加します。管理者の介入なしにファイルが削除されても通常は縮小しない「最高水準点」です。ディレクトリ。ファイルごとの正確な動作と増分は、基礎となるファイルシステムに依存します。Linuxext2 / 3/4システムでは、少なくとも信頼できる指標であると思います。)

bashは、空の完了が返された場合でも余分なスペースを追加します(これは、行の最後で完了する場合にのみ発生します)。あなたは追加することができます-o nospacecomplete、これを防止するためのコマンド。

残っている問題の1つは、カーソルをトークンの先頭にバックアップしてタブを押すと、デフォルトの補完が再び開始されることです。機能と考えてください;-)

(または${COMP_LINE:$COMP_POINT-1:1}、オーバーエンジニアリングが好きな場合は、いじくり回すことができますが、コマンドの途中でバックアップして完了しようとすると、bash自体が完了変数を確実に設定できません。)


6

dataディレクトリに特定の接尾辞が付いたファイルが含まれている場合、たとえば .outbash変数FIGNOREをに設定する".out"と、これらは無視されます。ディレクトリ名も使用できますが、これは現在の作業ディレクトリ名には役立ちません。

例:

RAID 1 HDDを使用して、物理ホスト上に数千の100KBテストファイルを作成します。

for i in {1..200000}; do dd if=/dev/urandom bs=102400 count=1 of=file$i.json; done

bash変数を設定します。
$ FIGNORE=".json"

テストファイルを作成します。
$ touch test.out

5,000ファイルでテスト:

$ ls *.json|wc -l
5587
$ vi test.out

viと単一の間の遅延なしtabの前にtest.out表示されます。

50,000ファイルでテスト:

$ ls *.json|wc -l
51854
$ vi test.out

単一のタブは、test.out表示される前に2分の1秒の遅延を作成します。

200,000ファイルでテストします。

$ ls *.json|wc -l
bash: /bin/ls: Argument list too long
$ ls | awk 'BEGIN {count=0} /.*.json/ {count++} END {print count}'
200000
$ vi test.out

viとtab前のシングルの間に1秒の遅延がtest.out表示されます。

参照:

man bashからのexcert

FIGNORE
              A  colon-separated  list  of  suffixes to ignore when performing filename completion (see READLINE below).  A filename whose suffix matches one of the entries in FIGNORE is
              excluded from the list of matched filenames.  A sample value is ".o:~".

1
役に立たない、約10万ファイルのディレクトリを作成してみてください。その後、私はない$ vi <tab><tab>、それは、とにかく多くの時間がかかります。:\
neizod 14年

それでも問題は解決しません。100k個の.jsonファイルと、という名前の単一のテキストファイルがあるとしfoo.txtます。ターニング FIGNORE='.json'上、I型$ vi <tab>とまだそれが私を完成させ半分分を待つ必要があります$ vi foo.txt。---実際のシナリオでは、そのディレクトリ内でファイルの種類を編集したり混合したりしませんが、FIGNOREタブをオンにして(偶然に)タブを押すと、キーボードのようなヒントがなく長時間キーボードがフリーズしDisplay all 188275 possibilities? (y or n)ますキーボードを戻すことができます。
ネイゾッド

@neizod-申し訳ありませんが、ディレクトリレベルでFIGNOREを動作させるために多くのシナリオを試してみましたが、役に立ちませんでした。カスタムソリューションが必要か、または単にそのホストでbash補完を無効にするか、姉妹サイトGillesに記載されているzshソリューションを試してください。
geedoubleya

申し訳ありませんが、お使いのシステムではわずか1秒です。私のシステムでは約30分です。だから私は、このソリューションを機能させるために新しいPCを買いに行くと思います。
neizod 14年

0

これがあなたが望むものだと思います(@ mr.spuraticからいくつかのコードを借りました)

これは、フルパスを使用してTABを押すことを妨げないことに注意してください(例: vim /directory/contains/lots/files<tab><tab>

function cd() {
  builtin cd "$@"
  local NOCOMPLETION=( "/" "/lib" )
  local IS_NOCOMPLETION=0
  for dir in "${NOCOMPLETION[@]}"
  do
    echo $dir
    if [[ $(pwd) == "$dir" ]]
    then
      echo "disable completion"
      bind "set disable-completion on"
      IS_NOCOMPLETION=1
      return
    fi                                                                                                                                                                                              
  done
  if [[ $IS_NOCOMPLETION -eq 0 ]]
  then
    echo "enable completion"
    bind "set disable-completion off"
  fi
}  

pushd/を忘れないでくださいpopd。これは連想配列ではなく通常の配列のみを使用するため、bash 3.xでも機能します。
mr.spuratic 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.