環境変数で Tab を押すと勝手に $ がエスケープされ邪魔すぎる

普段からよく使うパスは .bash_profile に環境変数として登録しておくと cd で飛び回ったり、ファイルを参照する時とか色々便利なので、活用している方も少なくないと思います。

今までは特に何の問題もなく、当たり前のように使っていたのですが、

今まで使っていた CentOS 6 のサポートも 2020年 11月末を持ってさよならするし、

古いバージョンをずっと使い続けるわけにも行かないので、OS を CentOS 7 (2024 年 06月までサポート) に乗せ替えましたと。

そして、今まで通りに、cd で環境変数を展開しようと Tab を押したら $ 文字が \$foo みたいな感じでエスケープされてしまい (バックスラッシュが付いてしまい)、変数 → フルパス に展開されず、邪魔で邪魔でしょうがありません。

shopt とは

この問題は、shopt のオプションを設定することで解決できますが、そもそも shopt って何かと言いますと。

shopt は、Bash シェルの様々なオプションを設定 / 解除するための組み込みコマンドです。

以下のように色んなオプションが存在しますが、基本的にはデフォルトのままで使っても構いませんが、軽く目を通して見て興味あるオプションがあれば試して見る感じで良いと思います。

  • -s <OPTION> : 有効化 (set)
  • -u <OPTION> : 無効化 (unset)
CentOS 7 : shopt オプション
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# man shopt
・・・
shopt [-pqsu] [-o] [optname ...]
  Toggle the values of variables controlling optional shell behavior.
  With no options, or with the -p option, a list of all settable options is displayed,
  with an indi‐ cation of whether or not each is set.
  The -p option causes output to be displayed in a form that may be reused as input.
  Other options have the following meanings:
  -s     Enable (set) each optname.
  -u     Disable (unset) each optname.
  -q     Suppresses  normal  output  (quiet mode); the return status indicates whether
         the optname is set or unset.
         If multiple optname arguments are given with -q, the return status
         is zero if all optnames are enabled; non-zero otherwise.
  -o     Restricts the values of optname to be those defined for the -o option
         to the set builtin.
  If either -s or -u is used with no optname arguments,
  the display is limited to those options which are set or unset, respectively.
  Unless otherwise noted, the shopt options are disabled (unset) by default.

  The return status when listing options is zero if all optnames are enabled,
  non-zero otherwise.
  When setting or unsetting options, the return status is zero unless an optname
  is not a valid shell option.

  The list of shopt options is:

  autocd
      If set, a command name that is the name of a directory is executed as if it were the
      argument to the cd command.  This  option  is  only  used  by  interactive shells.
  cdable_vars
      If set, an argument to the cd builtin command that is not a directory is assumed to
      be the name of a variable whose value is the directory to change to.
  cdspell
      If set,  minor errors in the spelling of a directory component in a cd command
      will be corrected.  The errors checked for are transposed characters, a missing
      character, and one character too many.
      If a correction is found, the corrected file name is printed, and the command proceeds.
      This option is  only  used  by  interactive shells.
  checkhash
      If set, bash checks that a command found in the hash table exists before trying to
      execute it.  If a hashed command no longer exists, a normal path search is performed.
  checkjobs
      If set, bash lists the status of any stopped and running jobs before exiting an
      interactive shell.  If any jobs  are  running, this causes the exit to be deferred
      until a second exit is attempted without an intervening command
      (see JOB CONTROL above).  The shell always postpones exiting if any jobs are stopped.
  checkwinsize
      If set, bash checks the window size after each command and, if necessary,
      updates the values of LINES and COLUMNS.
  cmdhist
      If set, bash attempts to save all lines of a multiple-line command in the same
      history entry.  This allows easy re-editing of multi-line commands.
  compat31
      If set, bash changes its behavior to that of version 3.1 with respect to quoted
      arguments to the [[ conditional command's =~ operator.
  compat32
      If  set,  bash  changes  its  behavior to that of version 3.2 with respect to
      locale-specific string comparison when using the [[ conditional command's
      < and > operators.
      Bash versions prior to bash-4.1 use ASCII collation and strcmp(3); bash-4.1 and later
      use the current locale's collation sequence and strcoll(3).
  compat40
      If set, bash changes its behavior to that of version 4.0 with respect to locale-specific
      string comparison when using the [[  conditional  command's  <  and  > operators
      (see previous item) and the effect of interrupting a command list.
  compat41
      If  set,  bash, when in posix mode, treats a single quote in a double-quoted parameter
      expansion as a special character.  The single quotes must match (an even number) and
      the characters between the single quotes are considered quoted.
      This is the behavior of posix mode through version 4.1.
      The default bash behavior remains as in previous versions.
  direxpand
      If  set, bash replaces directory names with the results of word expansion
      when performing filename completion.
      This changes the contents of the readline edit‐ ing buffer.
      If not set, bash attempts to preserve what the user typed.
  dirspell
      If set, bash attempts spelling correction on directory names during word completion
      if the directory name initially supplied does not exist.
  dotglob
      If set, bash includes filenames beginning with a `.' in the results of
      pathname expansion.
  execfail
      If set, a non-interactive shell will not exit if it cannot execute the file specified
      as an argument to the exec builtin command.
      An  interactive  shell  does  not exit if exec fails.
  expand_aliases
      If set, aliases are expanded as described above under ALIASES.
      This option is enabled by default for interactive shells.
  extdebug
      If set, behavior intended for use by debuggers is enabled:
      1. The -F option to the declare builtin displays the source file name and line number
         corresponding to each function name supplied as an argument.
      2. If the command run by the DEBUG trap returns a non-zero value, the next command
         is skipped and not executed.
      3. If  the  command  run by the DEBUG trap returns a value of 2,
         and the shell is executing in a subroutine (a shell function or a shell script
         executed by the . or source builtins), a call to return is simulated.
      4. BASH_ARGC and BASH_ARGV are updated as described in their descriptions above.
      5. Function tracing is enabled:  command substitution, shell functions, and
         subshells invoked with ( command ) inherit the DEBUG and RETURN traps.
      6. Error tracing is enabled:  command substitution, shell functions,
         and subshells invoked with ( command ) inherit the ERR trap.
  extglob
      If set, the extended pattern matching features described above under Pathname Expansion
      are enabled.
  extquote
      If set, $'string' and $"string" quoting is performed within ${parameter} expansions
      enclosed in double quotes.  This option is enabled by default.
  failglob
      If set, patterns which fail to match filenames during pathname expansion result in an
      expansion error.
  force_fignore
      If set, the suffixes specified by the FIGNORE shell variable cause words to be ignored
      when performing word completion even if the ignored words are the only
      possible completions.  See SHELL VARIABLES above for a description of FIGNORE.
      This option is enabled by default.
  globstar
      If  set,  the pattern ** used in a pathname expansion context will match all files
      and zero or more directories and subdirectories.
      If the pattern is followed by a /, only directories and subdirectories match.
  gnu_errfmt
      If set, shell error messages are written in the standard GNU error message format.
  histappend
      If set, the history list is appended to the file named by the value of the
      HISTFILE variable when the shell exits, rather than overwriting the file.
  histreedit
      If set, and readline is being used, a user is given the opportunity to re-edit
      a failed history substitution.
  histverify
      If set, and readline is being used, the results of history substitution
      are not immediately passed to the shell parser.
      Instead, the resulting line is  loaded into the readline editing buffer,
      allowing further modification.
  hostcomplete
      If  set, and readline is being used, bash will attempt to perform hostname
      completion when a word containing a @ is being completed
      (see Completing under READ‐ LINE above).  This is enabled by default.
  huponexit
      If set, the suffixes specified by the FIGNORE shell variable cause words to be
      ignored when performing word completion even if the ignored words are  the  only
      possible completions.  See SHELL VARIABLES above for a description of FIGNORE.
      This option is enabled by default.
  interactive_comments
      If set, allow a word beginning with # to cause that word and all remaining characters
      on that line to be ignored in an interactive shell (see COMMENTS  above).
      This option is enabled by default.
  lastpipe
      If set, and job control is not active, the shell runs the last command of a pipeline
      not executed in the background in the current shell environment.
  lithist
      If  set,  and  the  cmdhist option is enabled, multi-line commands are saved to the
      history with embedded newlines rather than using semicolon separators where possible.
  login_shell
      The shell sets this option if it is started as a login shell (see INVOCATION above).
      The value may not be changed.
  mailwarn
      If set, and a file that bash is checking for mail has been accessed since the last
      time it was checked, the message ``The mail in mailfile has been  read''  is displayed.
  no_empty_cmd_completion
      If set, and readline is being used, bash will not attempt to search the PATH for
      possible completions when completion is attempted on an empty line.
  nocaseglob
      If set, bash matches filenames in a case-insensitive fashion when performing pathname
      expansion (see Pathname Expansion above).
  nocasematch
      If set, bash matches patterns in a case-insensitive fashion when performing matching
      while executing case or [[ conditional commands.
  nullglob
      If set, bash allows patterns which match no files (see Pathname Expansion above) to
      expand to a null string, rather than themselves.
  progcomp
      If set, the programmable completion facilities (see Programmable Completion above)
      are enabled.  This option is enabled by default.
  promptvars
      If  set, prompt strings undergo parameter expansion, command substitution,
      arithmetic expansion, and quote removal after being expanded as described in
      PROMPT‐ ING above.  This option is enabled by default.
  restricted_shell
      The shell sets this option if it is started in restricted mode
      (see RESTRICTED SHELL below).  The value may not be changed.
      This is not reset when the startup files are executed, allowing the startup
      files to discover whether or not a shell is restricted.
  shift_verbose
      If set, the shift builtin prints an error message when the shift count exceeds
      the number of positional parameters.
  sourcepath
      If set, the source (.) builtin uses the value of PATH to find the directory containing
      the file supplied as an argument.  This option is enabled by default.
  xpg_echo
      If set, the echo builtin expands backslash-escape sequences by default.
・・・

環境変数として定義されたパスが展開されるように設定する

この問題を解決する前に、CentOS 6 と CentOS 7 の shopt のデフォルト設定を確認しておいた方が良いでしょう。

6.x と 7.x のマイナーバージョンによっても結果 (デフォルト設定値) が異なるかもしれませんが、とりあえずこんな感じでした。

CentOS 6 : shopt デフォルト設定
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# shopt
autocd          off
cdable_vars     off
cdspell         off
checkhash       off
checkjobs       off
checkwinsize    on
cmdhist         on
compat31        off
compat32        off
compat40        off


dirspell        off
dotglob         off
execfail        off
expand_aliases  on
extdebug        off
extglob         off
extquote        on
failglob        off
force_fignore   on
globstar        off
gnu_errfmt      off
histappend      off
histreedit      off
histverify      off
hostcomplete    on
huponexit       off
interactive_comments    on

lithist         off
login_shell     on
mailwarn        off
no_empty_cmd_completion off
nocaseglob      off
nocasematch     off
nullglob        off
progcomp        on
promptvars      on
restricted_shell        off
shift_verbose   off
sourcepath      on
xpg_echo        off
CentOS 7 : shopt デフォルト設定
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# shopt
autocd          off
cdable_vars     off
cdspell         off
checkhash       off
checkjobs       off
checkwinsize    on
cmdhist         on
compat31        off
compat32        off
compat40        off
compat41        off
direxpand       off
dirspell        off
dotglob         off
execfail        off
expand_aliases  on
extdebug        off
extglob         on
extquote        on
failglob        off
force_fignore   on
globstar        off
gnu_errfmt      off
histappend      on
histreedit      off
histverify      off
hostcomplete    off
huponexit       off
interactive_comments    on
lastpipe        off
lithist         off
login_shell     on
mailwarn        off
no_empty_cmd_completion off
nocaseglob      off
nocasematch     off
nullglob        off
progcomp        on
promptvars      on
restricted_shell        off
shift_verbose   off
sourcepath      on
xpg_echo        off

CentOS 7 では以下のオプションが加わってるように見えます。

  • compat41 : default off
  • direxpand : default off
  • lastpipe : default off

そして、シェルプロンプト上で、ディレクトリ・パス登録された $fooフルパスに展開するためのオプションは、direxpand なので、これを有効化すればこの問題は解決できます。

direxpand 設定前
1
2
3
4
5
# shopt | grep "direxpand"
direxpand       off

# foo=/etc/nginx/conf.d
# ls -l $foo/    #### ここで Tab を押すと $ がエスケープされる : $foo/ → \$foo/
direxpand 設定
1
# shopt -s direxpand
direxpand 設定後
1
2
3
4
5
# shopt | grep "direxpand"
direxpand       on

# foo=/etc/nginx/conf.d
# ls -l $foo/    #### ここで Tab を押すとパスが展開される : $foo/ → /etc/nginx/conf.d/

ログイン時に direxpand 設定適用

ログイン時に direxpand が適用されるように .bashrc に登録しておくと良いです。

.bashrc に direxpand 設定追加
1
2
3
4
5
6
# vi ~/.bashrc
・・・
shopt -s direxpand
・・・

# source ~/.bashrc    #### 現在のシェルに適用

終わりに

direxpand 以外にも便利なオプションとして、histappend と cdspell があります。

  • histappend : 全セッションの history 保存全てのログインセッションにおいて、history を全て記録します
  • cdspell : ディレクトリのスペルチェック別に使わなくてもいい気がしますが念のため

以上、Bash 環境変数の $ 文字が勝手にエスケープされる でした。