5

У меня есть эта раздражающая проблема в моей оболочке zsh, где функция где-то объявляется, и эта функция называется "cp", поэтому она переопределяет нормальное поведение cp. Я пытаюсь найти объявление функции, но не могу. Я уже посмотрел в нормальных местах .zshrc и различных других источников, которые включены в .zshrc, но пока ничего.

Другие вещи, которые я пробовал:

  • grep -r 'function cp' . (из ~)
  • whence -f cp (дает определение функции, но не там, где она объявлена)

Есть идеи?

4 ответа4

11

Мне нужно было сделать это сегодня и выяснить, whence -v выводит файл, содержащий определение функции.

$ whence -v function_name
function_name is a shell function from /path/to/file
3

Прежде всего, функция может быть определена без ключевого слова function поэтому лучший поиск будет

grep 'cp()' .*

Это будет искать через файлы, такие как .zshrc и .profile и еще много чего. Если это ничего не находит, вы также можете просмотреть различные файлы, загруженные zsh . Они перечислены в самом конце man zsh:

FILES
       $ZDOTDIR/.zshenv
       $ZDOTDIR/.zprofile
       $ZDOTDIR/.zshrc
       $ZDOTDIR/.zlogin
       $ZDOTDIR/.zlogout
       ${TMPPREFIX}*   (default is /tmp/zsh*)
       /etc/zsh/zshenv
       /etc/zsh/zprofile
       /etc/zsh/zshrc
       /etc/zsh/zlogin
       /etc/zsh/zlogout    (installation-specific - /etc is the default)

По умолчанию $ZDOTDIR должен быть вашим $HOME . Итак, эта команда должна найти ваш файл-нарушитель:

grep 'cp()\|cp ()' ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin /etc/zsh/zshenv \
 /etc/zsh/zprofile /etc/zsh/zshrc /etc/zsh/zlogin 

Я добавил \| так как вы можете также иметь пробелы между именем функции и самой функцией. Наконец, @Dennis указывает, что скобки также могут быть опущены, если вы используете ключевое слово function . Итак, чтобы быть еще более безопасным, сделайте это:

grep -E 'function cp|cp *\(\)' ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin \
  /etc/zsh/zshenv /etc/zsh/zprofile /etc/zsh/zshrc /etc/zsh/zlogin 
1

Более новые версии zsh (начиная с версии 5.4, добавлены в commit 34f70c5) поддерживают массив $functions_source как часть модуля zsh/parameter (документация: man zshmodules):

functions_source

Этот ассоциативный массив только для чтения отображает имена включенных функций на имя файла, содержащего источник функции.

Для функции автозагрузки, которая уже была загружена или помечена для автозагрузки с абсолютным путем, или путь которой был разрешен с помощью « functions -r », это файл, найденный для автозагрузки, преобразованный в абсолютный путь.

Для функции, определенной в теле скрипта или источника, это имя этого файла. В этом случае это точный путь, первоначально использованный для этого файла, который может быть относительным путем.

Для любой другой функции, включая любую определенную в интерактивном приглашении или функцию автозагрузки, путь которой еще не определен, это пустая строка. Тем не менее, элемент hash сообщается как определенный, только если функция присутствует: ключи к этому хешу те же, что и к $funcions .

Итак, вы можете сделать

echo $functions_source[cp]
0

Ответ Тердона уже дал вам соответствующую команду grep чтобы перехватить все возможные варианты определения функции.

Я хочу добавить еще два пункта.

  1. Чтобы получить список файлов, которые фактически считываются (например, нестандартный файл может быть получен из другого файла!), Вы можете вызвать zsh с включенной опцией SOURCE_TRACE :

    $ zsh -o sourcetrace
    +/etc/zshenv:1> <sourcetrace>
    +/home/user/.zshrc:1> <sourcetrace>
    +/home/user/.zcompdump:1> <sourcetrace>
    +/home/user/.zshrc-last:1> <sourcetrace>
    
  2. С помощью этого «grep-подхода» вы не поймаете функции, которые загружаются через встроенную функцию autoload . Итак, проверьте ваш fpath тоже:

    $ for i ($fpath) { ls -l "$i"/cp }
    

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .