理解我的 shell 脚本

m14*_*147 3 bash shell-script

我编写了一个在 bash 中使用的函数来自动挂载一个目录,~/tmp如果它不存在就创建一个:

# mkdir & mount auto
mnt() {
    dir="$1";
    mkdir ~/tmp/$dir;
    /usr/bin/sudo mount /dev/$dir ~/tmp/$dir;
    cd ~/tmp/$dir;
}
Run Code Online (Sandbox Code Playgroud)

几个问题 ...

dir="$1";
Run Code Online (Sandbox Code Playgroud)

将变量 dir 设置为 mnt 之后的任何输入
- 是否$1需要包含在其中""并且;每行之后是否需要一个?没有它会工作;吗?

/usr/bin/sudo mount /dev/$dir ~/tmp/$dir;
Run Code Online (Sandbox Code Playgroud)

我看了一个 YouTube 视频你需要知道的关于 Bash $PATH 的一切

在脚本中我应该写完整路径......

/usr/bin/sudo 
Run Code Online (Sandbox Code Playgroud)

而不是 ...

sudo
Run Code Online (Sandbox Code Playgroud)

这背后的原因是什么?

Sté*_*las 7

此功能的更好版本:

mnt() {
  typeset dir # for local scope for the variable.
              # assumes ksh88/pdksh/bash/zsh/yash. Replace typeset with
              # local for ash-based shells (or pdksh/bash/zsh)

  dir=$1 # here it's the only place where you don't need the quotes
         # though they wouldn't harm

  mkdir -p -- ~/tmp/"$dir" || return
     # quotes needed. mkdir -p creates intermediary directories as required
     # and more importantly here, doesn't fail if the directory already
     # existed.
     # We return from the function if mkdir failed (with the exit status
     # of mkdir). The -- is for the very unlikely even that your $HOME starts
     # with "-". So you may say it's a pedantic usage here. But it's good
     # habit to use it when passing an arbitrary (not known in advance)
     # argument to a command.

  sudo mount "/dev/$dir" ~/tmp/"$dir" || return
     # Or use /usr/bin/sudo if there are more than one sudo commands in $PATH
     # and you want to use the one in /usr/bin over other ones.
     # If you wanted to avoid calling an eventual "sudo" function  or alias 
     # defined earlier in the script or in a shell customisation file, 
     # you'd use "command sudo" instead.

  cd -P -- ~/tmp/"$dir" # another pedantic use of -P for the case where
                        # your $HOME contains symlinks and ".." components
}
Run Code Online (Sandbox Code Playgroud)

不需要分号。在 shell 提示下,你写:

cd /some/where
ls
Run Code Online (Sandbox Code Playgroud)

不是

cd /some/where;
ls;
Run Code Online (Sandbox Code Playgroud)

这在脚本中没有什么不同。您用于;在一行上分隔命令,如下所示:

cd /some/where; ls
Run Code Online (Sandbox Code Playgroud)

虽然,那么你宁愿写:

cd /some/where && ls
Run Code Online (Sandbox Code Playgroud)

这不是ls无条件运行,而是只有在cd成功时才运行。


jes*_*e_b 5

问题:

  • $1 是否需要包含在 "" 中

    简短的回答是肯定的

更多阅读

  • 是否需要一个?每行之后?没有;它会工作吗?

    ;是一个命令分隔符,仅当多个命令位于同一行时才需要,例如:echo "Hello, World"; echo。当命令像在脚本中一样位于不同的行上时,它是不必要的,但不会破坏任何内容。

  • 为什么要指定完整路径而不仅仅是命令名称?

    当您简单地键入命令名称时,您的路径将被解析为该命令第一次出现。在不同位置拥有多个命令的情况并不少见,尤其是在 GNU 工具和相同命令的其他变体存在的情况下。如果你没有指定你正在使用的命令的完整路径,你的 shell 将决定使用哪个,它可能不是你真正想要的。

我有点不同意总是指定完整路径,因为根据我的经验,这通常是没有必要的,我只关心它是否找到了该工具的某个版本。虽然也有例外,但我认为在考虑它们之前你应该更好地理解它们。例如,在我的环境中,我们大多使用不默认使用 GNU 工具的 unix 机器,但是机器上安装了许多工具,因此如果我需要对其中一台机器使用 GNU 版本的工具,我需要指定该工具的完整路径。


mnt() {
    dir="$1";                                   # Sets the value of dir to your first positional parameter
    mkdir ~/tmp/$dir;                           # Creates your a directory named after the value of $dir in $HOME/tmp/
    /usr/bin/sudo mount /dev/$dir ~/tmp/$dir;   # Mounts the device in /dev/$dir to your newly created folder (You better hope you set $1 properly)
    cd ~/tmp/$dir;                              # changes to your newly created/mounted directory.
}
Run Code Online (Sandbox Code Playgroud)

  • @PesaThe 不适合初学者,不。他/她观看的视频已经够混乱了。对初学者保持简单。回想一下你的数学课程。最初你只能加正整数,然后你学会了负数。后来你被告知你不能平方根一个负数。后来你可能会被告知你可以。这取决于你的经验。我不会教小学生_i_。回到变量。在极少数情况下,不带引号的变量是明确正确的做法。 (6认同)
  • @PesaThe“你不觉得吗”——绝对不是。没有很好的理由 ** 不 ** 引用和一千个很好的理由 ** 去 ** 引用。不断谈论无关紧要的罕见情况不会使任何人受益。另外这个问题是关于 shell 不一定是 bash。 (4认同)
  • 关于第三个 - IMO 编写 `/usr/bin/sudo` 并不是真正可取的。如果我刚刚在 `~/sudo` 中编译了一个新版本的 `sudo` 并将 `~/sudo` 添加到我的 `$PATH` 中 - 我希望所有脚本都使用它。有时使用 `/usr/bin/env <shell>` 代替 `/usr/bin/bash` 作为shebang,因为你不确定shell 在哪里(当然你仍然需要知道`/usr/ bin/env` 是)。最后,如何确定 `/usr/bin` 中确实存在 `sudo` 二进制文件?例如,系统管理员可能更愿意将其保存在“/usr/local/bin”中。 (3认同)