我在 Bash 中编写了以下脚本来删除给定特定数字范围的文件:
# *** Declare variables ***
SRC="${1}"
START="${2}"
END="${3}"
# *** Delete frame range ***
for frame in $(seq -f "%08g" "${START}" "${END}")
do
rm -vf "${SRC}${frame}"*
done
它在我的测试中运行良好,但是当我从实时服务器运行它时,它会以蜗牛般的速度删除文件。 rm 运行这么慢有什么原因吗?
谢谢!
答案1
在每个:
rm -vf "${SRC}${frame}"*
shell 首先需要扩展该 glob 以构造要传递给 的参数列表rm
。为此,它需要读取目录的内容并将每个文件名与模式进行匹配。
例如,如果$SRC
isfoo/bar
和$frame
is 00000000,则需要读取foo
目录的完整内容并将所有条目与bar00000000*
模式进行匹配,如果文件很多,则可能需要很长时间。
rm
,反过来需要在目录中找到这些文件,如果目录很大并且没有索引,这可能会花费一些时间。然后删除文件意味着修改目录(并更新其索引(如果有)),这对于大型目录来说可能又是昂贵的。
至少您应该尝试仅扩展一个 glob,以避免 shell 必须读取每一帧的整个目录。
其中zsh
具有<first-last>
十进制整数范围的全局运算符:
#! /bin/zsh -
src=$1 start=$2 end=$3
[[ $# -eq 3 && $start = <-> && $end = <-> && $end -ge $start ]] || {
print -ru2 "Usage: $ZSH_SCRIPT:t <src> <start> <end>"
exit 1
}
set -o extendedglob
range="(<$start-$end>~^?(#c8))" # range expressed on 8 characters
rm -vf -- $src$~range*
如果遇到系统对可以传递给命令的参数数量的限制,您可以将最后一行更改为:
print -rN -- $src$~range* | xargs -r0 rm -vf --