在 bash 脚本中查找问题

在 bash 脚本中查找问题

我正在编写一个程序打印指定目录的文件和目录。但我必须忽略某些类型的文件。我们将它们存储在.ignorefile.

因此,为了获取我想要的文件,我使用 find 函数。但是,我每次都会遇到同样的错误:No such file or directory

而且,当我在终端上尝试时,它可以使用相同的参数完美地工作。

一个例子 :

  • 在我的忽略文件中,我有:*.txt, *.cpp

  • 当我执行.sh文件时,我输入两个参数:忽略文件和目录。

  • 然后,当我扫描文件中的所有文本以构造参数文件时,我调用我的store()函数。

在这里你可以看到我的代码:

    function store(){
      dir="$1" 
      find_arg="$2" # Dir ! -name '*.txt' ! -name '*.cpp' -print
      echo $find_arg
      cmd=`find "$find_arg"`
      echo $cmd
    }

这里是构建 find_args 的函数:

function backup()
{
  if [ $1="-i" ] && [ -f $2 ]
  then
    backignore=$2
    if [ $3="-d" ] && [ -d $4 ]
    then
      directory=$4
      find_arg=" $directory"
      while IFS='' read -r line || [[ -n "$line" ]]; do
        find_arg+=" ! -name "
        find_arg+="'"
        find_arg+=$line
        find_arg+="'"
      done < "$backignore"
      find_arg+=" -print"
      store $directory "$find_arg"
    else
      echo "please entrer a right directory"
    fi
  else
    echo "Please enter a right ignore file"
  fi
}

backup $1 $2 $3 $4

我称之为“sh”文件

./file.sh -i ignorefile -d Source

输出:

Source ! -name '\*.cpp' ! -name '\*.txt' -print
Source/unix_backup/example_files/backignore   
Source/unix_backup/example_files/Documents/rep1/file3.txt
Source/unix_backup/example_files/Documents/rep1/file4.cpp   
Source/unix_backup/example_files/Documents/rep3 
Source/unix_backup/example_files/Documents/rep3/rep4 
Source/unix_backup/example_files/Documents/rep3/rep4/file7.txt    
Source/unix_backup/example_files/Documents/rep3/rep4/file8.cpp

答案1

find_arg作为单个参数传递(因为双引号),这意味着find正在努力寻找全部文件位于名为Dir ! -name '*.txt' ! -name '*.cpp' -print(是的,这是一个有效的目录名称)。尝试printf '%q\n' "$find_arg"查看传递给 的实际参数find。另外,如果你的 shell 支持数组,你可能应该使用它们来存储参数。和使用更多报价™!并且不要eval在这里使用 -find会很好地打印文件名。

答案2

  1. 您说您的 .ignorefile 有,*.txt, *.cpp但从显示的输出来看,它看起来像有\*.txt, \*.cpp。转义*是问题的根源,它告诉find排除带有文字星号的文件,而不是将其用作全局通配符。所以,不要这样做。

  2. 此版本的脚本修复了一些缺陷并稍微简化了它。除此之外,它将 arg 处理(并使用 sh 内置的 getopts)与backup()函数的主逻辑分开。

function store() {
    echo find "$@"
    find "$@"
}   

function backup() {
  directory="$1"
  backignore="$2"

  # skip comments and blank lines
  sed -e 's/#.*// ; /^[[:space:]]*$/d' "$backignore" |
      while IFS= read -r line ; do
          find_arg+=" ! -name '$line'"
      done 
  find_arg+=" -print"
  store "$directory" $find_arg
} 

usage() { 
    echo "$(basename $0) [ -d directory ] [ -i ignorefile ]"
    exit 1
}   

directory=''
backignore='.ignorefile'    # default

while getopts "i:d:h" opt ; do
  case "$opt" in
    d)  directory="$OPTARG" ;;
    i)  backignore="$OPTARG" ;;
    *) usage ;;
  esac 
done

[ -z "$directory" ] && echo "Please provide a directory." && usage

backup "$directory" "$backignore"

相关内容