Intereting Posts
Как объединить два логических тома, которые находятся на одном физическом томе в LVM? Согласование% CPU со средней загрузкой сверху Как объединить много сжатых файлов в один архив? Запустите команду перед любой командой терминала Удаление последнего символа одним словом, но только если символ присутствует – в bash Почему `* .ext` работает при поиске файла с расширением ‘ext’ Команда для извлечения аудио из видео без преобразования Является ли чтение видео с YouTube только для звука, доступного в командной строке? Заставить пользователя создать 775 папок разрешений Обновите список волшебных файлов и / или отправьте мои собственные Функция автозавершения Bash для SSHing в разные хосты Перезагрузка IPtables при перезагрузке, как мне сказать, что вызывает это Дублировать UUID для физических томов, но PV не входят в группу томов Текущий IP-адрес, видимый в Интернете? удалить опцию восстановления Windows из меню grub на fedora?

Отключить выполнение вкладки в Bash для какой-либо директории, содержащей большое количество файлов?

Я работаю с большим количеством файлов, которые хранятся в каталоге. Каждый раз, когда я вхожу в этот каталог и случайно дважды нажимаю Tab , для отображения файлов, соответствующих шаблону, требуется слишком много времени (может быть более нескольких минут), и я очень недовольна этим поведением.

Например, моя структура каталогов:

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

Поскольку мне все еще нравится завершение, есть ли вообще отключить эту функцию только в каталоге data/ ? Как установить тайм-аут на 5 секунд или скрипт, который автоматически отключает завершение, когда находится внутри определенного каталога?

Это не идеально, но опять-таки завершение 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 который вы можете touch к каталогу по мере необходимости; и угадывание размера каталога с помощью GNU stat . Вы можете использовать любой или все из этих трех вариантов.

(Метод stat – это только предположение , размер указанного каталога увеличивается с его содержимым, это «знак высокой воды», который обычно не уменьшается, когда файлы удаляются без какого-либо административного вмешательства. Это дешевле, чем определение реального содержимого потенциально большой каталог. Точное поведение и приращение на файл зависят от базовой файловой системы. Я считаю это надежным индикатором в системах linux ext2 / 3/4.)

bash добавляет дополнительное пространство, даже когда возвращается пустое завершение (это происходит только при завершении в конце строки). Вы можете добавить -o nospace в complete команду, чтобы предотвратить это.

Одно из оставшихся никейлов заключается в том, что если вы создадите резервную копию курсора до начала токена и нажмите вкладку, по умолчанию пополнение снова начнется. Считайте это особенностью 😉

(Или вы можете futz с ${COMP_LINE:$COMP_POINT-1:1} если вам нравится чрезмерная инженерия, но я нахожу, что bash не может надежно установить переменные завершения при резервном копировании и попытке завершения в середине команды .)

Если в вашем каталоге data содержатся файлы с определенным суффиксом, например .out , тогда вы можете установить переменную bash FIGNORE на ".out" и они будут проигнорированы. Хотя также можно использовать имена каталогов, это не помогает в текущих именах рабочих каталогов.

Пример:

Создайте тысячи тестовых файлов 100 КБ на физическом хосте с RAID-массивами 1-го уровня:

 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

Тест на 5000 файлов:

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

Задержка между vi и единственной 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 

Задержка в 1 секунду между vi и отдельной tab до 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:~". 

Угадайте, что это то, что вы хотите (заимствовал код из @ 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 }