"${-#*i}" は カレントシェルを変数展開したものだった

# 事の発端
/etc/profile に以下のような記述がある

```
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done
```

この `"${-#*i}"` が何か分からなくて小1時間調べる羽目に...

# "${-#*i}" とは
* 結論、 `カレントシェルのフラグ情報が入っているシェル変数を変数展開し、前方一致除去したもの`

## 分解して解釈する
### `$-` または `${-}` は カレントシェルが実行された時のオプションが入っている

```
$ echo "$-"
himBH
```

このオプションが何かというと（man bash 抜粋）
> -h　　Remember the location of commands as they are looked up for execution.  This is enabled by default.
> -i　　If the -i option is present, the shell is interactive.
> -m　　Monitor mode.  Job control is enabled.  This option is on by default for interactive shells on systems that support it (see JOB CONTROL above).  All processes run in a separate process group.  When a background job completes,  the  shell prints a line containing its exit status.
> -B　　The shell performs brace expansion (see Brace Expansion above).  This is on by default.
> -H　　Enable !  style history substitution.  This option is on by default when the shell is interactive.

### # は変数展開の前方一致除去

```
$ x=foobar; echo "${x}"
foobar

$ x=foobar; echo "${x#f}"　 // 前方一致で f を除去
oobar

$ x=foobar; echo "${x#foo}" // 前方一致で foo を除去
bar

$ x=foobar; echo "${x#*b}"  // 前方一致で *b を除去（*はワイルドカード）
ar
```

* これも man bash に書いてある

```
       ${parameter#word}
       ${parameter##word}
              Remove matching prefix pattern.  The word is expanded to produce a pattern just as in pathname expansion, and matched against the expanded value of parameter using the rules described under Pattern Matching below.  If  the  pattern  matches  the
              beginning  of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``#'' case) or the longest matching pattern (the ``##'' case) deleted.  If parameter is @ or *, the
              pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list.  If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the  array
              in turn, and the expansion is the resultant list.
```

### つまり "${-#*i}" とは
```
$ echo "${-}"
himBH

$ echo "${-#*i}"
mBH
```

# /etc/profile では何をやりたいのか
* 再掲

```
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done
```

> if [ "\${-#*i}" != "$-" ]; then

* カレントシェルが、インタラクティブかどうかを条件としている
* インタラクティブな場合は `true`
  * シェルスクリプトを実行
* インタラクティブではない場合は `false`
  * シェルスクリプトを実行するが、標準出力は捨てて、標準エラーを標準出力に出すようにしている

> . "$i"

* ~~ちなみに、この . は、カレントシェルのプロセスを置換して、処理を実行する exec の省略形である~~
* ちなみに、この `.` は、 ファイルを読み込んでカレントシェルでコマンドを実行する `source` の省略形である
* man bash 抜粋

>        .  filename [arguments]
>       source filename [arguments]
>              Read and execute commands from filename in the current shell environment and return the exit status of the last command executed
>              from filename.  If filename does not contain a slash, filenames in PATH are used to find the directory containing filename.  The
>              file  searched for in PATH need not be executable.  When bash is not in posix mode, the current directory is searched if no file
>              is found in PATH.  If the sourcepath option to the shopt builtin command is turned off, the PATH is not searched.  If any  argu-
>              ments  are  supplied,  they become the positional parameters when filename is executed.  Otherwise the positional parameters are
>              unchanged.  If the -T option is enabled, source inherits any trap on DEBUG; if it is not, any DEBUG trap  string  is  saved  and
>              restored  around the call to source, and source unsets the DEBUG trap while it executes.  If -T is not set, and the sourced file
>              changes the DEBUG trap, the new value is retained when source completes.  The return status is the status of  the  last  command
>              exited within the script (0 if no commands are executed), and false if filename is not found or cannot be read.