.pyenv/shims/python を覗いてみる

# 概要
pyenv の入り口がシェルスクリプトなのは知っていたが、そこを改めてよく見たことはなかったので一度見てみる。

# 内容
## `which python`
```bash
$ which python
/Users/yo314159265/.pyenv/shims/python
```
shims/以下のpythonが本体のようだ。
## `~/.pyenv/shims/python`
```bash:~/.pyenv/shims/python
#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x

program="${0##*/}"

export PYENV_ROOT="/Users/yo314159265/.pyenv"
exec "/usr/local/opt/pyenv/bin/pyenv" exec "$program" "$@"
```
1行目はshebang。環境でのbashで実行してくれる。
2行目は、set -eで、もしエラーが出たらすぐにスクリプトを止めるようにという意味。
3行目は、`[`テストコマンドで、真偽値を確認。`-n`は文字列がヌルでないかの確認。その場合設定される`-x`は、実行したコマンドを全て出力するかいなか。

なお、
* `-n` 文字列がヌルではないか
* `-z` 文字列がヌルか(つまり、長さがゼロ)か

また、
* `&` 前のコマンドの終了を待たずに実行する
* `&&` 前のコマンドが正常終了したら実行する

文字列の長さ０がヌル扱いなのと、真偽値が他の言語と逆（真が０で偽がそれ以外）なのは面白いなあと思います。

`program="{0##*/}"`
`${parameter##word}`の模様。`##`はlongest matchingで、`#`はshortest matching。[man](https://www.gnu.org/software/bash/manual/bash.html)。`#`はprefixの除去、`%`はpostfixの除去。
変数`0`は、ファイル名。(`1`以下は実行時の引数。)
総括すると、実行ファイル名がprogramに格納される。

exportで環境変数`PYENV_ROOT`にファイル名を格納。

そして、`$@`は引数（`1`, `2`とかの繋がったもの、あるいは`0`以外）
最後に、`/usr/local/opt/pyenv/bin/pyenv`を呼び出している。

## `/usr/local/opt/pyenv/bin/pyenv`
```bash
$ ls -l /usr/local/opt/pyenv/bin/pyenv
lrwxr-xr-x  1 yo314159265  staff  16 May 30 01:50 /usr/local/opt/pyenv/bin/pyenv -> ../libexec/pyenv
```
symlinkでした。

## `/usr/local/opt/pyenv/libexec/pyenv`
```bash:/usr/local/opt/pyenv/libexec/pyenv
#!/usr/bin/env bash
set -e

if [ "$1" = "--debug" ]; then
  export PYENV_DEBUG=1
  shift
fi

if [ -n "$PYENV_DEBUG" ]; then
  # https://wiki-dev.bash-hackers.org/scripting/debuggingtips#making_xtrace_more_useful
  export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
  set -x
fi

abort() {
  { if [ "$#" -eq 0 ]; then cat -
    else echo "pyenv: $*"
    fi
  } >&2
  exit 1
}

if enable -f "${BASH_SOURCE%/*}"/../libexec/pyenv-realpath.dylib realpath 2>/dev/null; then
  abs_dirname() {
    local path
    path="$(realpath "$1")"
    echo "${path%/*}"
  }
else
  [ -z "$PYENV_NATIVE_EXT" ] || abort "failed to load \`realpath' builtin"

  READLINK=$(type -P greadlink readlink | head -1)
  [ -n "$READLINK" ] || abort "cannot find readlink - are you missing GNU coreutils?"

  resolve_link() {
    $READLINK "$1"
  }

  abs_dirname() {
    local path="$1"

    # Use a subshell to avoid changing the current path
    (
    while [ -n "$path" ]; do
      cd_path="${path%/*}"
      if [[ "$cd_path" != "$path" ]]; then
        cd "$cd_path"
      fi
      name="${path##*/}"
      path="$(resolve_link "$name" || true)"
    done

    echo "$PWD"
    )
  }
fi

if [ -z "${PYENV_ROOT}" ]; then
  PYENV_ROOT="${HOME}/.pyenv"
else
  PYENV_ROOT="${PYENV_ROOT%/}"
fi
export PYENV_ROOT

if [ -z "${PYENV_DIR}" ]; then
  PYENV_DIR="$PWD"
fi

if [ ! -d "$PYENV_DIR" ] || [ ! -e "$PYENV_DIR" ]; then
  abort "cannot change working directory to \`$PYENV_DIR'"
fi

PYENV_DIR=$(cd "$PYENV_DIR" && echo "$PWD")
export PYENV_DIR


shopt -s nullglob

bin_path="$(abs_dirname "$0")"
for plugin_bin in "${bin_path%/*}"/plugins/*/bin; do
  PATH="${plugin_bin}:${PATH}"
done
# PYENV_ROOT can be set to anything, so it may happen to be equal to the base path above,
# resulting in duplicate PATH entries
if [ "${bin_path%/*}" != "$PYENV_ROOT" ]; then
  for plugin_bin in "${PYENV_ROOT}"/plugins/*/bin; do
    PATH="${plugin_bin}:${PATH}"
  done
fi
export PATH="${bin_path}:${PATH}"

PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${PYENV_ROOT}/pyenv.d"
if [ "${bin_path%/*}" != "$PYENV_ROOT" ]; then
  # Add pyenv's own `pyenv.d` unless pyenv was cloned to PYENV_ROOT
  PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${bin_path%/*}/pyenv.d"
fi
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:/usr/local/etc/pyenv.d:/etc/pyenv.d:/usr/lib/pyenv/hooks"
for plugin_hook in "${PYENV_ROOT}/plugins/"*/etc/pyenv.d; do
  PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${plugin_hook}"
done
PYENV_HOOK_PATH="${PYENV_HOOK_PATH#:}"
export PYENV_HOOK_PATH

shopt -u nullglob


command="$1"
case "$command" in
"" )
  { pyenv---version
    pyenv-help
  } | abort
  ;;
-v | --version )
  exec pyenv---version
  ;;
-h | --help )
  exec pyenv-help
  ;;
* )
  command_path="$(command -v "pyenv-$command" || true)"
  if [ -z "$command_path" ]; then
    if [ "$command" == "shell" ]; then
      abort "shell integration not enabled. Run \`pyenv init' for instructions."
    else
      abort "no such command \`$command'"
    fi
  fi

  shift 1
  if [ "$1" = --help ]; then
    if [[ "$command" == "sh-"* ]]; then
      echo "pyenv help \"$command\""
    else
      exec pyenv-help "$command"
    fi
  else
    exec "$command_path" "$@"
  fi
  ;;
esac
```
少しずつ見ていく。
```bash
#!/usr/bin/env bash
set -e
```
ここは前に見た通り。エラー時すぐ止める。

```bash
if [ "$1" = "--debug" ]; then
  export PYENV_DEBUG=1
  shift
fi
```
もし、1個目の引数が`--debug`なら、`PYENV_DEBUG`を`1`にセットする。(1個目じゃないと駄目なのか)
shiftは、引数のリストをずらす。つまり`$2`が`$1`になる。なるほど。

```bash
if [ -n "$PYENV_DEBUG" ]; then
  # https://wiki-dev.bash-hackers.org/scripting/debuggingtips#making_xtrace_more_useful
  export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
  set -x
fi
```
`PYENV_DEBUG`がセットされていれば、`PS4`にデバッグに有用な情報が出力されるよう。
`-x`は前に見たコマンドを表示するもの。
なお、([link](https://www.thegeekstuff.com/2008/09/bash-shell-take-control-of-ps1-ps2-ps3-ps4-and-prompt_command/))
* PS1: Default interaction prompt
* PS2: Continuation interactive prompt
* PS3: Prompt used by “select” inside shell script
* PS4: Used by “set -x” to prefix tracing output
(LINENOとかが出力できるのも`-x`によるのだろう。)

```bash
abort() {
  { if [ "$#" -eq 0 ]; then cat -
    else echo "pyenv: $*"
    fi
  } >&2
  exit 1
}
```
`$#`は引数の数。`$*`は引数を一語にしたもの。
`-` は入力を標準出力から受け取ること。つまり、標準出力からの入力を出力する。
実はこの正確な動作は理解できてない。

```bash
if enable -f "${BASH_SOURCE%/*}"/../libexec/pyenv-realpath.dylib realpath 2>/dev/null; then
  abs_dirname() {
    local path
    path="$(realpath "$1")"
    echo "${path%/*}"
  }
else
  [ -z "$PYENV_NATIVE_EXT" ] || abort "failed to load \`realpath' builtin"

  READLINK=$(type -P greadlink readlink | head -1)
  [ -n "$READLINK" ] || abort "cannot find readlink - are you missing GNU coreutils?"

  resolve_link() {
    $READLINK "$1"
  }
  abs_dirname() {
    local path="$1"

    # Use a subshell to avoid changing the current path
    (
    while [ -n "$path" ]; do
      cd_path="${path%/*}"
      if [[ "$cd_path" != "$path" ]]; then
        cd "$cd_path"
      fi
      name="${path##*/}"
      path="$(resolve_link "$name" || true)"
    done

    echo "$PWD"
    )
  }
fi
```
>Enable and disable builtin shell commands.
> Syntax
       enable [-a] [-dnps] [-f filename] [name …]
Key
   -f   Load the new builtin command name from shared object filename, on systems that
        support dynamic loading.

ここでは、`pyenv-realpath.dylib`から`realpath`を取り込もうとしている。このrealpathを活用して、`abs_dirname()`が準備される。

```bash
if [ -z "${PYENV_ROOT}" ]; then
  PYENV_ROOT="${HOME}/.pyenv"
else
  PYENV_ROOT="${PYENV_ROOT%/}"
fi
export PYENV_ROOT
```
ここでは、`PYENV_ROOT`を設定することを目指している。なお、これははじめに設定してある。
そして、改めて、最後の`/`を除去してある。

```bash
if [ -z "${PYENV_DIR}" ]; then
  PYENV_DIR="$PWD"
fi

if [ ! -d "$PYENV_DIR" ] || [ ! -e "$PYENV_DIR" ]; then
  abort "cannot change working directory to \`$PYENV_DIR'"
fi

PYENV_DIR=$(cd "$PYENV_DIR" && echo "$PWD")
export PYENV_DIR
```
`PYENV_DIR`を設定する。もしまだPYENV_DIRが設定されていなければ、現在のディレクトリに設定しようとする。設定されていても、ディレクトリでも存在もしなければエラーとなる。
ここで、PYENV_DIRに移動する。どうして再代入するのかはわからない。（SIMLINK対策？わからない。）
なお、`PYENV_ROOT=$HOME/.pyenv`を.bashrcに記載して欲しいとは言われている。

```bash
shopt -s nullglob
```
オプションをセットしているが、nullglobは該当ファイルがないときに空文字列を生成するかどうか。[参考](https://qiita.com/anqooqie/items/a2b607fe984ec982fa21)

```bash
bin_path="$(abs_dirname "$0")"
for plugin_bin in "${bin_path%/*}"/plugins/*/bin; do
  PATH="${plugin_bin}:${PATH}"
done
# PYENV_ROOT can be set to anything, so it may happen to be equal to the base path above,
# resulting in duplicate PATH entries
if [ "${bin_path%/*}" != "$PYENV_ROOT" ]; then
  for plugin_bin in "${PYENV_ROOT}"/plugins/*/bin; do
    PATH="${plugin_bin}:${PATH}"
  done
fi
export PATH="${bin_path}:${PATH}"
```
`PATH`の設定。
* `/usr/local/opt/pyenv/plugins/python-build/bin`
    * pyenv-install
    * pyenv-uninstall
    * python-build
* `/usr/local/opt/pyenv/libexec`
    * pyenv
    * pyenv---version
    * ....

```bash
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${PYENV_ROOT}/pyenv.d"
if [ "${bin_path%/*}" != "$PYENV_ROOT" ]; then
  # Add pyenv's own `pyenv.d` unless pyenv was cloned to PYENV_ROOT
  PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${bin_path%/*}/pyenv.d"
fi
PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:/usr/local/etc/pyenv.d:/etc/pyenv.d:/usr/lib/pyenv/hooks"
for plugin_hook in "${PYENV_ROOT}/plugins/"*/etc/pyenv.d; do
  PYENV_HOOK_PATH="${PYENV_HOOK_PATH}:${plugin_hook}"
done
PYENV_HOOK_PATH="${PYENV_HOOK_PATH#:}"
export PYENV_HOOK_PATH
```
`PYENV_HOOK_PATH`は大体`/usr/local/opt/pyenv/pyenv.d`とかを指すのだろう。

```bash
shopt -u nullglob
```
nullglobをアンセット。

```bash
command="$1"
case "$command" in
"" )
  { pyenv---version
    pyenv-help
  } | abort
  ;;
-v | --version )
  exec pyenv---version
  ;;
-h | --help )
  exec pyenv-help
  ;;
* )
  command_path="$(command -v "pyenv-$command" || true)"
  if [ -z "$command_path" ]; then
    if [ "$command" == "shell" ]; then
      abort "shell integration not enabled. Run \`pyenv init' for instructions."
    else
      abort "no such command \`$command'"
    fi
  fi

  shift 1
  if [ "$1" = --help ]; then
    if [[ "$command" == "sh-"* ]]; then
      echo "pyenv help \"$command\""
    else
      exec pyenv-help "$command"
    fi
  else
    exec "$command_path" "$@"
  fi
  ;;
esac
```
ここで、引数により呼び出されるファイルが示される。
* ""
    * pyenv---version
    * pyenv-help
* -v | --version
    * exec pyenv---version
* -h | --help
    * exec pyenv-help
* \*
    * exec "\\$command_path" "\\$@"
    * もし、次に--helpがくれば、pyenv helpもしくはpyenv-help


`command_path`は、`"$(command -v "pyenv-$command" || true)"`で得られる。これは、`PATH`に`/usr/local/opt/pyenv/libexec`を追加しているからこそできることだろう。

ちょっと寄り道して、`pyenv global`を見てみることにする。

## `/usr/local/opt/pyenv/libexec/pyenv-global`(寄り道)
```bash:/usr/local/opt/pyenv/libexec/pyenv-global
set -e
[ -n "$PYENV_DEBUG" ] && set -x

# Provide pyenv completions
if [ "$1" = "--complete" ]; then
  echo system
  exec pyenv-versions --bare
fi

versions=("$@")
PYENV_VERSION_FILE="${PYENV_ROOT}/version"

if [ -n "$versions" ]; then
  pyenv-version-file-write "$PYENV_VERSION_FILE" "${versions[@]}"
else
  OLDIFS="$IFS"
  IFS=: versions=($(
    pyenv-version-file-read "$PYENV_VERSION_FILE" ||
    pyenv-version-file-read "${PYENV_ROOT}/global" ||
    pyenv-version-file-read "${PYENV_ROOT}/default" ||
    echo system
  ))
  IFS="$OLDIFS"
  for version in "${versions[@]}"; do
    echo "$version"
  done
fi
```
shebangとコメントは削除した。
少しずつ見ていく。

```bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x
```
恒例のもの。

```bash
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
  echo system
  exec pyenv-versions --bare
fi
```
コンプリートオプションが設定されていた場合の動作。
```bash
versions=("$@")
PYENV_VERSION_FILE="${PYENV_ROOT}/version"
```
引数を`versions`に納め、VERSION_FILEを指定。

```bash
if [ -n "$versions" ]; then
  pyenv-version-file-write "$PYENV_VERSION_FILE" "${versions[@]}"
else
  OLDIFS="$IFS"
  IFS=: versions=($(
    pyenv-version-file-read "$PYENV_VERSION_FILE" ||
    pyenv-version-file-read "${PYENV_ROOT}/global" ||
    pyenv-version-file-read "${PYENV_ROOT}/default" ||
    echo system
  ))
  IFS="$OLDIFS"
  for version in "${versions[@]}"; do
    echo "$version"
  done
fi
```
ここで、設定するか表示するかの違い。
設定する場合は、`pyenv-version-file-write`を使って、`PYENV_VERSION_FILE`に書き込んでいる模様。
ここで、`versions=("$@")`および"${versions[@]}"に注意。実は、Python 2系と3系の二つを指定できる模様。
そのために配列での操作にあんっているようだ。

## `/usr/local/opt/pyenv/libexec/pyenv-version-file-write`
```bash:/usr/local/opt/pyenv/libexec/pyenv-version-file-write
#!/usr/bin/env bash
# Usage: pyenv version-file-write <file> <version>

set -e
[ -n "$PYENV_DEBUG" ] && set -x

PYENV_VERSION_FILE="$1"
shift || true
versions=("$@")

if [ -z "$versions" ] || [ -z "$PYENV_VERSION_FILE" ]; then
  pyenv-help --usage version-file-write >&2
  exit 1
fi

# Make sure the specified version is installed.
pyenv-prefix "${versions[@]}" >/dev/null

# Write the version out to disk.
# Create an empty file. Using "rm" might cause a permission error.
> "$PYENV_VERSION_FILE"
for version in "${versions[@]}"; do
  echo "$version" >> "$PYENV_VERSION_FILE"
done
```
少しずつファイルに追記している。ん。追記している？
よくみると、直前にリダイレクトで`> "$PYENV_VERSION_FILE"`と初期化を行っていた。これで毎回1行しか書かれない。
これでバージョンが指定されるのか。

## 再び`~/.pyenv/shims/python`へ。(最終行)
```bash:~/.pyenv/shims/python
exec "/usr/local/opt/pyenv/bin/pyenv" exec "$program" "$@"
```
そうか、元々は、`command`が`exec`の場合を見たかったのだ。

## そして`/usr/local/opt/pyenv/libexec/pyenv-exec`(最終章)
shebangとコメントは省く。
```bash:/usr/local/opt/pyenv/libexec/pyenv-exec
set -e
[ -n "$PYENV_DEBUG" ] && set -x

# Provide pyenv completions
if [ "$1" = "--complete" ]; then
  exec pyenv-shims --short
fi

PYENV_VERSION="$(pyenv-version-name)"
PYENV_COMMAND="$1"

if [ -z "$PYENV_COMMAND" ]; then
  pyenv-help --usage exec >&2
  exit 1
fi

export PYENV_VERSION
PYENV_COMMAND_PATH="$(pyenv-which "$PYENV_COMMAND")"
PYENV_BIN_PATH="${PYENV_COMMAND_PATH%/*}"

OLDIFS="$IFS"
IFS=$'\n' scripts=(`pyenv-hooks exec`)
IFS="$OLDIFS"
for script in "${scripts[@]}"; do
  source "$script"
done

shift 1
if [ "${PYENV_BIN_PATH#${PYENV_ROOT}}" != "${PYENV_BIN_PATH}" ]; then
  # Only add to $PATH for non-system version.
  export PATH="${PYENV_BIN_PATH}:${PATH}"
fi
exec "$PYENV_COMMAND_PATH" "$@"
```
少しずつ見ていく。
```bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x
```
お決まりの文句。
```bash
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
  exec pyenv-shims --short
fi
```
コンプリーションズのオプションが設定されていた時の動作。
```bash
PYENV_VERSION="$(pyenv-version-name)"
PYENV_COMMAND="$1"

if [ -z "$PYENV_COMMAND" ]; then
  pyenv-help --usage exec >&2
  exit 1
fi
```
VERSIONとCOMMANDの取得。今回のコマンドは、`python`のはず。
なお、`pyenv-version-name`は`PYENV_VERSION`をよむか、`pyenv-version-file-read`を読んだりして取得している。
```bash
export PYENV_VERSION
PYENV_COMMAND_PATH="$(pyenv-which "$PYENV_COMMAND")"
PYENV_BIN_PATH="${PYENV_COMMAND_PATH%/*}"
```
ここで、pyenv-whichを使ってCOMMAND_PATHを取得している。(後でみる。)

```bash
OLDIFS="$IFS"
IFS=$'\n' scripts=(`pyenv-hooks exec`)
IFS="$OLDIFS"
for script in "${scripts[@]}"; do
  source "$script"
done
```
IFSは、"internal field separator". [link](https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting)
続けて、`pyenv-hooks exec`をこのIFSで呼ぶことができている。そして、exec以下のファイルが実行されることになる。(前処理かなあ)

```bash
shift 1
if [ "${PYENV_BIN_PATH#${PYENV_ROOT}}" != "${PYENV_BIN_PATH}" ]; then
  # Only add to $PATH for non-system version.
  export PATH="${PYENV_BIN_PATH}:${PATH}"
fi
exec "$PYENV_COMMAND_PATH" "$@"
```
そして最終的に`exec "$PYENV_COMMAND_PATH" "$@"`される。

さて、ここでpyenv-whichが./pyenv/versionを読み出しているところが見られれば良いのだが。
## そして`/usr/local/opt/pyenv/libexec/pyenv-which`(最終章最終回)
少しずつ見ていく。
```bash:/usr/local/opt/pyenv/libexec/pyenv-which
set -e
[ -n "$PYENV_DEBUG" ] && set -x
```
決まり文句。
```bash
# Provide pyenv completions
if [ "$1" = "--complete" ]; then
  exec pyenv-shims --short
fi

if [ "$2" = "--nosystem" ]; then
  system=""
else
  system="system"
fi
```
特定オプション処理。
```bash
remove_from_path() {
  local path_to_remove="$1"
  local path_before
  local result=":${PATH//\~/$HOME}:"
  while [ "$path_before" != "$result" ]; do
    path_before="$result"
    result="${result//:$path_to_remove:/:}"
  done
  result="${result%:}"
  echo "${result#:}"
}
```
`":${PATH//\~/$HOME}:"`はreplace all。
remove_from_pathそのままの処理をしている。

```bash
PYENV_COMMAND="$1"

if [ -z "$PYENV_COMMAND" ]; then
  pyenv-help --usage which >&2
  exit 1
fi
```
PYENV_COMMANDの格納。ここでは、pythonのはず。
```bash
OLDIFS="$IFS"
IFS=: versions=(${PYENV_VERSION:-$(pyenv-version-name)})
IFS="$OLDIFS"

for version in "${versions[@]}" "$system"; do
  if [ "$version" = "system" ]; then
    PATH="$(remove_from_path "${PYENV_ROOT}/shims")"
    PYENV_COMMAND_PATH="$(command -v "$PYENV_COMMAND" || true)"
  else
    PYENV_COMMAND_PATH="${PYENV_ROOT}/versions/${version}/bin/${PYENV_COMMAND}"
  fi
  if [ -x "$PYENV_COMMAND_PATH" ]; then
    break
  fi
done
```
`${PYENV_VERSION:-$(pyenv-version-name)}`の`:-`はもしunsetなら後者を使うということ。
ここでやっと、
`PYENV_COMMAND_PATH="${PYENV_ROOT}/versions/${version}/bin/${PYENV_COMMAND}"`
が見つかる。

```bash
OLDIFS="$IFS"
IFS=$'\n' scripts=(`pyenv-hooks which`)
IFS="$OLDIFS"
for script in "${scripts[@]}"; do
  source "$script"
done
```
hooksの処理。（おそらく前処理）
```bash
if [ -x "$PYENV_COMMAND_PATH" ]; then
  echo "$PYENV_COMMAND_PATH"
else
  any_not_installed=0
  for version in "${versions[@]}"; do
    if [ "$version" = "system" ]; then
      continue
    fi
    if ! [ -d "${PYENV_ROOT}/versions/${version}" ]; then
      echo "pyenv: version \`$version' is not installed (set by $(pyenv-version-origin))" >&2
      any_not_installed=1
    fi
  done
  if [ "$any_not_installed" = 1 ]; then
    exit 1
  fi

  echo "pyenv: $PYENV_COMMAND: command not found" >&2

  versions="$(pyenv-whence "$PYENV_COMMAND" || true)"
  if [ -n "$versions" ]; then
    { echo
      echo "The \`$1' command exists in these Python versions:"
      echo "$versions" | sed 's/^/  /g'
      echo
      echo "Note: See 'pyenv help global' for tips on allowing both"
      echo "      python2 and python3 to be found."
    } >&2
  fi

  exit 127
fi
```
そして、ここでpathが出力される。↓
```bash
if [ -x "$PYENV_COMMAND_PATH" ]; then
  echo "$PYENV_COMMAND_PATH"
```
完。
## おまけ
```bash
$ ~/.pyenv/versions/3.10.0/bin/python
Python 3.10.0 (default, Jun  6 2022, 16:40:39) [Clang 11.0.3 (clang-1103.0.32.59)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
# 感想
楽しかった。