Shell脚本添加CASE分支后文件校验功能异常求助
解决安全删除脚本添加选项后的文件检查错误
你遇到的问题太常见了——当给脚本加了-r这类命令行选项后,开头的文件存在性检查会把选项本身当成要删除的文件来验证,自然就抛出了“Input is NOT a file!”的错误,毕竟-r根本不是一个文件路径嘛。
问题根源分析
原来的脚本开头有个遍历所有参数的循环:
for input in "$@"; do if ! [ -e "$input" ]; then echo "Input is NOT a file!" exit 1 fi done
当你执行./sdell -r file1.txt时,$@包含了-r和file1.txt两个参数,循环会先检查-r是否是文件,显然不满足条件,直接触发错误退出了。
修复方案:分离选项与文件参数
我们需要先处理命令行选项,把选项和实际要操作的文件参数分开,这样文件存在性检查只针对真正的文件路径。下面是修改后的完整脚本:
#!/bin/bash #Purpose = Safe delete #Created on 20-03-2018 #Version 0.9 #START ##Constants## dir="/home/cunha/LIXO" # 处理命令行选项,分离选项与文件参数 files=() size_threshold=0 # 用于-s选项的大小阈值 while [[ $# -gt 0 ]]; do case "$1" in -r) echo "启用递归删除测试模式" shift # 跳过当前选项参数 ;; -s) # 处理-s选项,获取大小阈值(单位KB) size_threshold="$2" echo "设置文件大小阈值为 ${size_threshold}KB" shift 2 # 跳过选项和对应的参数值 ;; *) # 非选项参数,加入待处理文件列表 files+=("$1") shift ;; esac done # 仅检查待处理文件是否存在 for input in "${files[@]}"; do if ! [ -e "$input" ]; then echo "输入 '$input' 不是一个有效的文件/路径!" exit 1 fi done ###main### # 遍历所有待处理文件 for file in "${files[@]}"; do # 处理-s选项:判断文件大小是否超过阈值 if [[ $size_threshold -gt 0 ]]; then file_size=$(du -k "$file" | cut -f1) if [[ $file_size -le $size_threshold ]]; then echo "文件 '$file' 大小(${file_size}KB)未超过阈值,跳过处理" continue fi fi fwe="${file%.*}" # 检查目标目录是否已有同名归档文件 if [[ -f "$dir/$fwe.tar.bz2" ]]; then echo "归档文件 $fwe.tar.bz2 已存在于回收站" # 比较原文件与归档文件的修改时间,保留更新的版本 if [[ "$file" -nt "$dir/$fwe.tar.bz2" ]]; then echo "原文件更新,替换旧归档文件" rm "$dir/$fwe.tar.bz2" && tar -czPf "$fwe.tar.bz2" "$file" && mv "$fwe.tar.bz2" "$dir" fi else echo "压缩文件并移动到回收站" tar -czPf "$fwe.tar.bz2" "$file" && mv "$fwe.tar.bz2" "$dir" fi done
关键修改点说明
- 新增选项处理循环:用
while循环遍历参数,把选项和文件参数分离到不同的逻辑分支,选项处理后直接跳过,文件参数存入files数组。 - 调整文件检查逻辑:现在只检查
files数组里的内容,不会再把选项标记当成文件验证。 - 实现
-s选项功能:添加了-s分支来接收大小阈值,在主循环里判断文件大小是否超过阈值再处理。 - 修复时间比较错误:原代码中
"$file" -nt "$2"是错误的,改成了比较原文件和回收站里的归档文件的修改时间。
现在你执行./sdell -r file1.txt或者./sdell -s 100 large_file.log都能正常工作啦。
内容的提问来源于stack exchange,提问作者user9540477
相关产品推荐
相关产品推荐

