Rap*_*ael 47 bash shell-script rm
所以,我删除了我的主文件夹(或者,更准确地说,我有写权限的所有文件)。发生的事情是我有
build="build"
...
rm -rf "${build}/"*
...
<do other things with $build>
Run Code Online (Sandbox Code Playgroud)
在 bash 脚本中,在不再需要之后$build,删除声明及其所有用法——但是rm. Bash 愉快地扩展到rm -rf /*. 是的。
我觉得自己很傻,安装了备份,重新做我丢失的工作。试图摆脱耻辱。
现在,我想知道:编写 bash 脚本的技巧是什么,以便此类错误不会发生,或者至少不太可能发生?例如,我是否写过
FileUtils.rm_rf("#{build}/*")
Run Code Online (Sandbox Code Playgroud)
在 Ruby 脚本中,解释器会抱怨build没有被声明,所以语言保护了我。
我在 bash 中考虑过的,除了 corraling rm(正如相关问题中提到的许多答案一样,这并非没有问题):
rm -rf "./${build}/"*rm在当前目录之外操作时,它的变体/参数化需要交互。(找不到。)类似的效果。是这样,还是有其他方法可以编写在这个意义上“健壮”的 bash 脚本?
Kus*_*nda 77
set -u
Run Code Online (Sandbox Code Playgroud)
或者
set -o nounset
Run Code Online (Sandbox Code Playgroud)
这将使当前的 shell 将未设置变量的扩展视为错误:
$ unset build
$ set -u
$ rm -rf "$build"/*
bash: build: unbound variable
Run Code Online (Sandbox Code Playgroud)
set -u并且set -o nounset是POSIX shell 选项。
但是,空值不会触发错误。
为此,使用
$ rm -rf "${build:?Error, variable is empty or unset}"/*
bash: build: Error, variable is empty or unset
Run Code Online (Sandbox Code Playgroud)
的扩展${variable:?word}将扩展到值,variable除非它为空或未设置。如果它为空或未设置,word则将显示在标准错误上,并且 shell 会将扩展视为错误(该命令不会被执行,如果在非交互式 shell 中运行,这将终止)。离开:了会引发错误只为一个没有设置的,就像下set -u。
${variable:?word}是POSIX 参数扩展。
这些都不会导致交互式 shell 终止,除非set -e(或set -o errexit) 也有效。${variable:?word}如果变量为空或未设置,则导致脚本退出。set -u如果与set -e.
至于你的第二个问题。没有办法限制rm在当前目录之外不能工作。
的 GNU 实现rm有一个--one-file-system选项,可以阻止它递归删除挂载的文件系统,但这与我相信我们可以在不将rm调用包装在实际检查参数的函数中一样接近。
作为旁注: ${build}完全等同于$build除非扩展作为字符串的一部分发生,其中紧随其后的字符是变量名称中的有效字符,例如 in "${build}x"。
Cen*_*ane 12
我将建议使用test/[ ]
如果你这样写你的脚本,你会很安全:
build="build"
...
[ -n "${build}" ] || exit 1
rm -rf "${build}/"*
...
Run Code Online (Sandbox Code Playgroud)
在[ -n "${build}" ]检查到"${build}"是一个非零的长度的字符串。
该||是在bash逻辑OR运算符。如果第一个命令失败,它会导致运行另一个命令。
就这样,一直${build}是空的/未定义的/等。脚本会退出(返回码为 1,这是一个通用错误)。
如果您删除所有用途,这也会保护您,${build}因为[ -n "" ]它将始终为假。
使用test/的好处[ ]是还有许多其他更有意义的检查可以使用。
例如:
[ -f FILE ] True if FILE exists and is a regular file.
[ -d FILE ] True if FILE exists and is a directory.
[ -O FILE ] True if FILE exists and is owned by the effective user ID.
Run Code Online (Sandbox Code Playgroud)