> For the complete documentation index, see [llms.txt](https://huataihuang.gitbook.io/cloud-atlas-draft/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://huataihuang.gitbook.io/cloud-atlas-draft/develop/shell/bash/special_shell_variable.md).

# shell的特殊变量

|  变量  | 含义                                                |
| :--: | ------------------------------------------------- |
| `$0` | 当前脚本的文件名                                          |
| `$n` | 传递给脚本或函数的参数。n 是一个数字，表示第几个参数。例如，第一个参数是$1，第二个参数是$2。 |
| `$#` | 传递给脚本或函数的参数个数。                                    |
| `$*` | 传递给脚本或函数的所有参数。                                    |
| `$@` | 传递给脚本或函数的所有参数。被双引号(" ")包含时，与 $\* 稍有不同，下面将会讲到。     |
| `$?` | 上个命令的退出状态，或函数的返回值。                                |
| `$$` | 当前Shell进程ID。对于 Shell 脚本，就是这些脚本所在的进程ID。            |

> `$*` 和 `$@` 都表示传递给函数或脚本的所有参数，不被双引号(`" "`)包含时，都以`"$1"` `"$2"` … `"$n"` 的形式输出所有参数。

但是当它们被双引号(`" "`)包含时，`"$*"` 会将所有的参数作为一个整体，以`"$1 $2 … $n"`的形式输出所有参数；`"$@"` 会将各个参数分开，以`"$1" "$2" … "$n"` 的形式输出所有参数。

`$?` 可以获取上一个命令的退出状态。所谓退出状态，就是上一个命令执行后的返回结果。

退出状态是一个数字，一般情况下，大部分命令执行成功会返回 `0`，失败返回 `1`。

不过，也有一些命令返回其他值，表示不同类型的错误。

## 案例

### 检查脚本参数

假如我们有一个脚本，要求传递的参数是某个目录，我们的脚本逻辑需要检查：

* 是不是传递了一个参数
* 传递的参数是不是一个存在的目录

```bash
#!/bin/sh
if [ "$#" -ne 1 ] || ! [ -d "$1" ]; then
  echo "Usage: $0 DIRECTORY" >&2
  exit 1
fi
```

> 以上脚本逻辑简单清晰

## 参考

* [Shell特殊变量：Shell $0, $#, $\*, $@, $?, $$和命令行参数](http://c.biancheng.net/cpp/view/2739.html)
* [Checking for the correct number of arguments](https://stackoverflow.com/questions/4341630/checking-for-the-correct-number-of-arguments)
