私は大量のファイルを扱っており、それらをディレクトリに保存しています。そのディレクトリに移動して誤って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
) を使用して、いろいろいじくり回すことだと思います。
これすべきあなたにとっては良いことですが、5月意図しない副作用(場合によっては期待される完了の変更など)が発生することがあります。
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 つのオプションのいずれか、またはすべてを使用できます。touch
stat
(stat
方法推測に過ぎない報告されたディレクトリ サイズはその内容に応じて大きくなりますが、これは「最高水準点」であり、管理者の介入なしにファイルが削除されても通常は縮小しません。これは、潜在的に大きなディレクトリの実際の内容を決定するよりも安価です。正確な動作とファイルごとの増分は、基礎となるファイルシステムによって異なります。少なくとも Linux ext2/3/4 システムでは、これは信頼できる指標だと思います。
bash は、空の補完が返された場合でも余分なスペースを追加します (これは行末で補完した場合にのみ発生します)。これを防ぐには、コマンド-o nospace
にを追加できます。complete
残る 1 つの問題は、カーソルをトークンの先頭まで戻して Tab キーを押すと、デフォルトの補完が再び開始されることです。これは機能として考えてください ;-)
(あるいは、オーバーエンジニアリングが好きならいじってみるのもいいです${COMP_LINE:$COMP_POINT-1:1}
が、コマンドの途中で戻って補完を試みた場合、bash 自体が補完変数を確実に設定できないことがわかりました。)
答え2
data
ディレクトリに特定のサフィックスを持つファイルが含まれている場合、例えば .out
、bash
変数FIGNORE
を に設定する".out"
と、これらは無視されます。ディレクトリ名も使用できますが、これは現在作業中のディレクトリ名には役立ちません。
例:
RAID 1 HDD を搭載した物理ホスト上に 100 KB のテスト ファイルを数千個作成します。
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 と single tab
beforeの間に遅延はtest.out
ありません。
テスト場所50,000ファイル:
$ ls *.json|wc -l
51854
$ vi test.out
単一のタブでは、表示されるまでにほんの一瞬の遅延が発生しますtest.out
。
テスト場所20万ファイル:
$ 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 と single tab
beforeの間に 1 秒の遅延がtest.out
表示されます。
参考文献:
マンバッシュからの抜粋
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:~".
答え3
これがあなたが望んでいるものだと思います(@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
}