我正在通过我制作的一些脚本有效地制作一个回收站。
第一个脚本几乎是 rm 命令的替代方案(它不是实际删除文件,而是将其移动到已删除的文件夹)。
我已设法允许脚本将多个文件移动到已删除的文件夹:
sh moveToBin file1 file2 fil3 (similar to: rm file1 file2 file3)
我的第一个脚本的开头是:
#!/bin/bash
for param in "$@"
do
..
..
(main part of my code)
将每个参数(文件)一一移至已删除的文件夹中。我现在正在尝试合并添加 switch 参数,但我不太确定如何合并它。
上面的方法适用sh moveToBin file1 file2 file3
,但我如何合并第一个参数(仅第一个)可以是开关-i
(要求删除)、-v
(确认删除)、-iv
(要求删除然后确认删除)的可能性。
因此该开关仅适用于$1
.我尝试了一个叫做 getopts 的东西,但我不熟悉它的用法。一旦使用开关,这适用于$2
以后的情况,即
sh moveToBin -i file1 file2
这要求删除 file1,在我决定之后,它会要求删除 file2 我想到了类似的东西,但我怀疑它是否会起作用。有什么帮助吗?
counter=1
for param in "$@"
do
while [[ if $param = "-*" && counter -eq1]];
do
getopts "iv" arg;
case "$arg" in
i) read -p "want to delete $param ?" ans
if [ ans =~ ^[Y][y] ]
then
#run main code for that param value
fi;;
v) #run main code for that param value
echo "file @param deleted";;
esac
counter=$((counter+1))
continue
done
#run main code for that param value
done
while循环条件意味着它是第一个参数并且该参数以连字符开头。
答案1
内置getopts
解析选项。您只需对所有选项运行一次,然后处理剩下的操作数(非选项参数)。getopts
允许调用者随意编写例如moveToBin -iv file1
或moveToBin -i -v file1
,并且您可以编写moveToBin -- -file
处理以破折号开头的文件名(后面的任何内容--
都被解释为操作数)。
getopts
跟踪已经通过OPTIND
变量处理了多少个参数。当它完成它的工作时,OPTIND
是第一个操作数的索引;由于参数从 1 开始编号,这意味着第一个OPTIND-1
参数是选项。
只要您正在解析选项,您就不知道要处理的文件列表。因此通过设置变量来记住该选项,并稍后查询该变量。
#!/bin/bash
confirm=
verbose=
while getopts 'iv' OPTLET; do
case $OPTLET in
i) confirm=y;;
v) verbose=y;;
\?) exit 3;; # Invalid option; getopts already printed an error message
esac
done
shift $((OPTIND-1))
for file in "$@"; do
if [[ -n $confirm ]]; then
read -p "want to delete $param ?" ans
if [[ $ans != [Yy]* ]]; then
continue # the user said no, so skip this file
fi
fi
… # do that moving stuff
if [[ -n $verbose ]]; then
echo "File $file deleted"
fi
done
请注意,getopts
遵循传统的选项解析模型,其中第一个操作数之后的任何内容都是非选项。换句话说,在 中moveToBin -i foo -v bar
,有-i
选项,然后是三个文件foo
、-v
和bar
。如果您想允许 GNU 选项解析模型(其中选项可以与操作数混合),getopts
则不是特别有帮助。 bash 的getopts
内置解析 GNU 长选项也无法解析(--verbose
会像-v -e -r -b -o -s -e
加上不支持的错误一样进行解析-
)。
答案2
#!/usr/bin/env bash
VERBOSE=n
while getopts "vC:" opt; do
case $opt in
v)
VERBOSE=y
;;
C)
echo got $OPTARG
;;
esac
done
shift $(($OPTIND - 1))
echo "soooo verbose is $VERBOSE"
for x in "$@"; do
echo "still got: $x"
done
然后在通常的 chmoddery 之类的之后:
$ ./gopt hi there
soooo verbose is n
still got: hi
still got: there
$ ./gopt -v hi there
soooo verbose is y
still got: hi
still got: there
$ ./gopt -C cats -v hi there
got cats
soooo verbose is y
still got: hi
still got: there
$