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