
저는 많은 수의 파일을 작업하고 있으며 해당 파일을 디렉토리에 저장하고 있습니다. 해당 디렉토리에 들어가서 실수로 Tab두 번 누를 때마다 패턴과 일치하는 파일이 표시되는 데 너무 오랜 시간(아마도 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
이 프롬프트 기능은 구성된 디렉터리 중 하나를 입력할 때 변수를 설정합니다. 수정된 완료 동작은 변수가 비어 있지 않은 경우에만 적용됩니다.그리고이렇게 하면 빈 문자열에서 완성을 시도하는 경우에만 부분 이름을 완성할 수 있습니다( -z "$cur"
완전히 완료되지 않도록 하려면 조건을 제거하세요). 자동 작동을 위해 이 두 줄을 주석 처리하세요 printf
.
다른 옵션에는 필요한 경우 디렉토리에 배치 할 수 있는 디렉토리별 .noautocomplete
플래그 파일 과 GNU를 사용하여 디렉토리 크기를 추측하는 기능이 포함됩니다 . 이 세 가지 옵션 중 일부 또는 전부를 사용할 수 있습니다.touch
stat
( stat
방법그냥 추측이에요, 보고된 디렉터리 크기는 해당 내용에 따라 증가합니다. 이는 "하이 워터 마크"이며 일반적으로 관리자 개입 없이 파일이 삭제될 때 줄어들지 않습니다. 잠재적으로 큰 디렉터리의 실제 내용을 결정하는 것보다 비용이 저렴합니다. 각 파일의 정확한 동작과 증분은 기본 파일 시스템에 따라 다릅니다. 나는 이것이 적어도 Linux ext2/3/4 시스템에서는 신뢰할 수 있는 지표라고 생각합니다. )
빈 완성이 반환되더라도 bash는 추가 공백을 추가합니다(이는 줄 끝 완성에서만 발생합니다). 이런 일이 발생하지 않도록 -o nospace
명령을 추가할 수 있습니다 .complete
남은 사소한 문제는 커서를 마크업의 시작 부분으로 다시 이동하고 Tab을 누르면 기본 완성이 다시 시작된다는 것입니다. 기능이라고 생각하세요 ;-)
(또는 과도한 엔지니어링을 좋아한다면 자유롭게 사용할 수 있지만 ${COMP_LINE:$COMP_POINT-1:1}
백업하고 명령 중간에 완료하려고 할 때 bash 자체가 완료 변수를 안정적으로 설정하지 않는다는 것을 발견했습니다.)
답변2
data
디렉토리에 특정 접미사가 붙은 파일이 포함되어 있는 경우예를 들어 .out
bash
, 변수를 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와 Single tab
before 사이에는 test.out
지연이 없습니다 .
테스트 대상50,000문서:
$ ls *.json|wc -l
51854
$ vi test.out
개별 탭이 표시되기까지 몇 분의 1초 정도의 지연이 발생합니다 test.out
.
테스트 대상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
tab
vi 와 Single 사이에는 1초의 지연이 있습니다 test.out
.
인용하다:
man bash에서 발췌
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에서 일부 코드를 빌림)
전체 경로(예: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
}