删除 Linux shell 脚本卡住的情况

删除 Linux shell 脚本卡住的情况

此脚本应删除垃圾箱目录的内容。如果-a使用该选项,脚本应删除全部垃圾箱中的文件。否则,脚本应一一显示垃圾箱中的文件名,并要求用户确认是否应将其删除。

if test ! -f ~/TAM/dustbin/*
then
  echo "this directory is empty"
else
  for resfile in ~/TAM/dustbin/* 
  do
    if test -f $resfile ; then
      echo "Do you want to delete $resfile"
      echo "Y/N"
      read ans
      if test $ans = Y ; then 
        rm $resfile
        echo "File $resfile was deleted"
      fi
    fi
  done
fi

以上是有效的,但是它会导致报告一些错误甚至尽管它仍然在错误发生后执行下一行的代码而不会崩溃。

错误:

./remove: line 4: test: to many arguments

(当垃圾箱中有超过 2 个文件时会发生这种情况。)

./remove: line 4: test: root/TAM/dustbin/NewFile2: binary operator expected

(当文件是 newfile2 而不是 newfile3 时,会发生这种情况。)

还有人对我如何-a删除文件夹中的所有内容而不分别询问每个文件有任何意见吗?

答案1

对于第一个问题,基本上,您给了太多参数test(在我看来,您粘贴的第一行实际上是脚本的第四行)。如果您的情况有多个文件,您将test -f file1 file2 file3…需要test等待二元运算符(例如,“-a”表示 AND)之后-f file1以及之后的下一个表达式,依此类推。

至于为脚本提供和处理参数以自动删除文件而不要求确认,您可以test在 $1 上使用相同的参数(这将是脚本的第一个命令行参数)。

答案2

你有两个主要问题。

第一个问题是第一个命令中发生的情况:test ! -f ~/TAM/dustbin/*。首先 shell 扩展通配符模式~/TAM/dustbin/*,然后将结果列表传递给test命令。如果有多个匹配文件,则这将不起作用。

使用任何 Bourne 风格的 shell,您可以将匹配列表保存在位置参数中,并检查第一个单词是否存在(如果不存在,则模式不匹配任何内容)。

set ~/TAM/dustbin/*
if ! test -f "$1"; then
  echo "this directory is empty"

(看这个答案了解在 ksh、bash 和 zsh 中将不匹配的 glob 模式扩展为空列表的方法。)

请注意,该目录可能不为空:它可能包含点文件(名称以 开头的文件.,通配符模式*会跳过这些文件。如果您还想检查点文件是否存在,最简单的便携式方法是使用find:

if [ "$(cd ~/TAM/dustbin && find . | head -n 1)" = "." ]; then
  echo "this directory is empty"
else
  set ~/TAM/dustbin/..?* ~/TAM/dustbin/.[!.]* ~/TAM/dustbin/*
  for x; do
    if [ -f "$x" ]; then
      # $x is a regular file
    elif [ -e "$x" ]; then
      # $x is a directory or other special file
    else
      # $x is an unexpanded non-matching pattern
    fi
  done
fi

(请注意,test -f仅匹配常规文件;用于-e测试文件是否存在。)

脚本中的另一个普遍问题是您没有防止文件名包含 shell 特殊字符。"$foo"始终在变量替换和命令替换周围使用双引号"$(foo)"如果文件名包含空格或\[?*.

我认为这是一个学习练习。如果不是:

#!/bin/bash
setopt nullglob
rm -ri ~/TAM/dustbin/*

答案3

#!/bin/bash
dir="$HOME/TAM/dustbin"

# check if the dir is empty
shopt -s nullglob
files=("$dir"/*)
if (( ${#files[@]} == 0 )); then
    echo "the directory is empty"
    exit
fi

# handle command line arguments
all=false
while getopts :a opt; do
    case $opt in
        a) all=true ;;
        ?) echo "unknown option: -$OPTARG"; exit 1 ;;
    esac
done
shift $((OPTIND - 1))

# perform the deletion
if $all; then
    command rm "$dir"/*
else
    command rm -i "$dir"/*
fi

相关内容