validation参数到一个Bash脚本

我想出了一个基本的帮助,以便在不需要的时候自动删除大量文件夹。

#!/bin/bash rm -rf ~/myfolder1/$1/anotherfolder rm -rf ~/myfolder2/$1/yetanotherfolder rm -rf ~/myfolder3/$1/thisisafolder 

这是这样引起的:

 ./myscript.sh <{id-number}> 

问题是,如果你忘记inputid-number (就像我那样) ,那么它可能会删除很多你真的不想删除的东西。

有没有一种方法可以将任何forms的validation添加到命令行参数? 在我的情况下,这将是很好的检查,a)有一个参数,b)它的数字,和c)该文件夹存在; 在继续脚本之前。

 #!/bin/sh die () { echo >&2 "$@" exit 1 } [ "$#" -eq 1 ] || die "1 argument required, $# provided" echo $1 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $1 provided" while read dir do [ -d "$dir" ] || die "Directory $dir does not exist" rm -rf "$dir" done <<EOF ~/myfolder1/$1/anotherfolder ~/myfolder2/$1/yetanotherfolder ~/myfolder3/$1/thisisafolder EOF 

编辑 :我错过了有关检查目录是否存在的部分,所以我join了,完成脚本。 此外,还处理了评论中提出的问题; 修正了正则expression式,从==切换到eq

据我所知,这应该是一个可移植的,POSIX兼容的脚本; 它不使用任何bashisms,这实际上很重要,因为Ubuntu上的/bin/sh实际上是dash ,而不是bash

Brian CampbellBrian Campbell这个解决scheme虽然高贵而且执行得很好,但有一些问题,所以我想我会提供自己的解决scheme。

问题一:

  • ~/foo中的波浪号不会扩展到heredocs中的homedirectory。 而且当它被read语句read或在rm语句中引用时。 这意味着你会得到No such file or directory错误。
  • 分叉grep和这样的基本操作是愚蠢的。 特别是当你使用蹩脚的shell来避免bash的“沉重”的重量。
  • 我也注意到了一些引用问题,例如围绕他的echo的参数扩展。
  • 虽然很less见,但解决scheme无法处理包含换行符的文件名。 (在sh几乎没有解决scheme可以应付他们 – 这就是为什么我几乎总是喜欢bash ,它使用得当时更加防弹和更难以利用)。

虽然,使用/bin/sh为你的hashbang意味着你必须不惜一切代价避免bash isms,你可以使用所有你喜欢的bash isms,甚至在Ubunutu上,或者当你诚实的时候使用#!/bin/bash在顶部。

所以,这是一个更小,更干净,更透明,可能“更快”,更防弹的bash解决scheme。

 [[ -d $1 && $1 != *[^0-9]* ]] || { echo "Invalid input." >&2; exit 1; } rm -rf ~/foo/"$1"/bar ... 
  1. 注意rm声明中的$1左右的引号!
  2. 如果$1为空, -d检查也会失败,所以这是两个检查之一。
  3. 我避免了正则expression式的原因。 如果你必须在bash中使用=~ ,你应该把正则expression式放在一个variables中。 无论如何,像我这样的球体总是可取的,并且支持更多的bash版本。

我会用bash的[[

 if [[ ! ("$#" == 1 && $1 =~ ^[0-9]+$ && -d $1) ]]; then echo 'Please pass a number that corresponds to a directory' exit 1 fi 

我发现这个常见问题是一个很好的信息来源。

没有上面的答案那么简单,但是仍然有效:

 #!/bin/bash if [ "$1" = "" ] then echo "Usage: $0 <id number to be cleaned up>" exit fi # rm commands go here 

使用'-z'来testing空string,'-d来检查目录。

 if [[ -z "$@" ]]; then echo >&2 "You must supply an argument!" exit 1 elif [[ ! -d "$@" ]]; then echo >&2 "$@ is not a valid directory!" exit 1 fi 

使用set -u会导致任何未设置的参数引用立即使脚本失败。

http://www.davidpashley.com/articles/writing-robust-shell-scripts.html

testing的手册页( man test )提供了所有可用的操作符,可以在bash中用作布尔运算符。 在你的脚本(或函数)的开始处使用这些标志来进行inputvalidation,就像你在任何其他编程语言中一样。 例如:

 if [ -z $1 ] ; then echo "First parameter needed!" && exit 1; fi if [ -z $2 ] ; then echo "Second parameter needed!" && exit 2; fi 

您可以通过执行如下操作来紧凑地validation点a和b:

 #!/bin/sh MYVAL=$(echo ${1} | awk '/^[0-9]+$/') MYVAL=${MYVAL:?"Usage - testparms <number>"} echo ${MYVAL} 

这给了我们…

 $ ./testparams.sh Usage - testparms <number> $ ./testparams.sh 1234 1234 $ ./testparams.sh abcd Usage - testparms <number> 

这个方法在sh中应该可以正常工作。

老post,但我想我可以贡献反正。

一个脚本可以说是没有必要的,并且可以从命令行执行一些对通配符的容忍。

  1. 野外任何地方匹配 让我们删除任何发生的“文件夹”

     $ rm -rf ~/*/folder/* 
  2. 壳迭代。 让我们用一行删除特定的前后文件夹

     $ rm -rf ~/foo{1,2,3}/folder/{ab,cd,ef} 
  3. shell迭代+ var(BASHtesting)。

     $ var=bar rm -rf ~/foo{1,2,3}/${var}/{ab,cd,ef}