任务是编写一个带有 n+1 个参数的 shell 脚本,其中第一个参数是目录,其余的是指定文件,并将删除除指定文件之外的所有文件。
例如打电话rmexcept . '*.jpg' '*.png'
cd $1
for i in “${@:2}”
do
find . -type f -not -name $i -delete
done
这是我的尝试。但是,它仅适用于 1 个指定文件(例如rmexcept . '*.jpg'
)。如果有超过 1 个文件(例如rmexcept . '*.jpg' '*.png'
),则所有文件都将被删除。我不知道出了什么问题,因为我相信我已经创建了一个 for 循环。
答案1
试试这个(内嵌评论):
#!/bin/bash
set -f # Prevent e.g. *.txt from being expanded here
dir=$1 # Get the target directory and
shift # remove from list of args
cmd="find $dir -type f"
while (( "$#" )) # While there are more arguments left
do
cmd="$cmd -not -name $1" # add to not match
shift # and remove from list of arguments
done
cmd="$cmd -exec rm -i {} ;" # finally execute rm on the remaining matches
echo $cmd # Print the final find command
$cmd # And execute it
我添加-i
了rm
以便它在删除每个文件之前询问。但当然,你可以调整它。
答案2
与以下机制相同拉恩凯奥的回答,但作为一个更最小的无变量POSIX外壳函数:
rmexcept(){ find "$1" $(shift; printf " -not -name %s" ${@}) -exec rm '{}' \; ;}
shell 的
printf
命令代替for
orwhile
循环完成主要工作。使用
bash
shell,shift
可以用参数扩展来替换:rmexcept(){ find "$1" $(printf " -not -name %s" ${@:2}) -exec rm '{}' \; ;}
find
请注意,如果结果或rm
命令长于 返回的数字,则两个函数都不会完成作业getconf ARG_MAX
。看:Bash 命令行和输入限制。