【问题标题】:String after find recognized as one parameter查找后的字符串被识别为一个参数
【发布时间】:2025-12-24 05:20:09
【问题描述】:

我重新创建了几天前发布的杂乱脚本,它更加简洁。现在我有以下问题:

我的脚本根据所有给定的参数创建了一个变量字符串,因为需要将部分参数转换为查找参数。

例如,我的脚本创建以下内容:

FINDVAR="/home /ex -type f -name \*.sh"

当我尝试执行以下操作时: find $FINDVARfind ${FINDVAR} 甚至 $(find $FINDVAR) 我没有收到任何输出。

但是当我echo $FINDVAR 找到后粘贴输出,效果很好!

我也试过了

find "$FINDVAR"

但这给了我

find: `/home /ex -type f -name \*.sh': 没有这样的文件或目录

所以,这会将字符串识别为 1 个参数。

有什么解决办法吗?我已经坚持了几个小时了

编辑:真的找不到它,也许你们中的一个可以看看它?我省略了长荷兰语的回声

#!/bin/bash

#FUNCTIONS
#Foutmelding
charfout(){
  echo "Uw ingevoerde eerste letter met argument -l is ongeldig."
  echo "Gebruik: $0 -e <extensie> -l <a>/<a-c>"
}

extfout() {
  echo 1>&2;
  echo 1>&2;
  exit
 }

#Help
help() {
  echo
  echo "--- Help ---"
  echo
  exit
}


#Opties in getopt instellen + argumenten in volgorde plaatsen (mappen achter case-opties)
OPTS=$(getopt -o e:hl:b:f:s: -l "help,nn,nr,fout" -n "ExamenScript" -- "$@");
eval set -- "$OPTS";

#Case doorlopen om opties aan respectievelijke variabelen toe te wijzen
while true; do
  case "$1" in
    -e)
      shift;
      if [ -n "$1" ]; then
        BESTANDSEXTENSIE=$1;
        shift;
      fi
      ;;
    -h|--help)
      shift;
      help;
      ;;
    -l)
      shift;
      if [ -n "$1" ]; then
        BEGINLETTER=$1;
        shift;
      fi
      ;;
    -b)
      shift;
      if [ -n "$1" ]; then
        BLOCKDEVICE=$1;
        shift;
      fi
      ;;
    --nn)
      shift;
      NONUMBERS=true;
      ;;
    --nr)
      shift;
      NORECURSION=true;
      ;;
    -f|--fout)
      shift;
      if [ -n "$1" ]; then
        FOUTLOG=true;
        shift;
      fi
      ;;
    -s)
      shift;
      if [ -n "$1" ]; then
        ZOEKEN=$1;
        shift;
      fi
      ;;
    --)
      shift;
      break;
      ;;
  esac
done

#De overige argumenten, ergo de te-doorzoeken-folders, in een array plaatsen
TEDOORZOEKENFOLDERS=("$@")

#De array van folders als eerste argumenten van de find functie opgeven
#FINDARGUMENTEN=$(printf "%s " "${TEDOORZOEKENFOLDERS[@]}")

#Nagaan of er een block device gemount dient te worden
if [[ $BLOCKDEVICE ]]; then
  echo "Gelieve admin rechten te geven om het block-device te kunnen mounten."
  sudo mount /dev/$BLOCKDEVICE /mnt
  TEDOORZOEKENFOLDERS+=(" /mnt") #Pad van gemounte drive aan array toevoegen
fi

#Beargumenteren dat er naar bestanden moet gezocht worden (type -f)
FINDARGUMENTEN="-type f"

#Indien de no-recursion vlag gebruikt is, enkel level 1 mappen toestaan
if [[ $NORECURSION ]]; then
  FINDARGUMENTEN=$FINDARGUMENTEN" -maxdepth 1"
fi

#De extensie implementeren door een naamfilter aan find toe te voegen
#Indien geen extensie opgegeven, foutmelding
if [[ $BESTANDSEXTENSIE ]]; then
  FINDARGUMENTEN=$FINDARGUMENTEN" -name \*.${BESTANDSEXTENSIE}"
else
  extfout
fi

#Nagaan hoeveel karakters er aan het -l argument toegewezen zijn
case ${#BEGINLETTER} in
  0) #Niets toegewezen
    ;;
  1) FINDARGUMENTEN=$FINDARGUMENTEN" -name ${BEGINLETTER}*" #Beginnen met een letter
    ;;
  3) FINDARGUMENTEN=$FINDARGUMENTEN" -name [${BEGINLETTER}]*" #Beginnenn met een letter-range
    ;;
  *) charfout
    ;;
  esac

#Indien de no-numbers vlag gebruikt is, nummers verbieden in de bestandsnaam
if [[ $NONUMBERS ]]; then
  FINDARGUMENTEN=$FINDARGUMENTEN" \! -name '*[0-9]*'"
fi

find "${TEDOORZOEKENFOLDERS[@]} $FINDARGUMENTEN"

【问题讨论】:

  • 尝试运行不带引号的findcommand:find ${FINDVAR}

标签: bash shell find


【解决方案1】:

尝试使用数组:

FINDVAR=( /home /ex -type f -name \*.sh )
find "${FINDVAR[@]}"

这应该通过适当的转义/引用正确处理所有参数。


你需要类似的东西

FINDARGUMENTEN=( -type f )

if [[ $NORECURSION ]]; then
    FINDARGUMENTEN+=( -maxdepth 1 )
fi

if [[ $BESTANDSEXTENSIE ]]; then
    FINDARGUMENTEN+=( -name "\\*.${BESTANDSEXTENSIE}" )
fi

case ${#BEGINLETTER} in
    1) FINDARGUMENTEN+=( -name "${BEGINLETTER}\\* ) ;;
    3) FINDARGUMENTEN+=( -name "[${BEGINLETTER}]\\*" ) ;;
esac

if [[ $NONUMBERS ]]; then
    FINDARGUMENTEN+=( '\!' -name '*[0-9]*' )
fi

find "${TEDOORZOEKENFOLDERS[@]}" "${FINDARGUMENTEN[@]}"

我不确定双反斜杠 - 你必须尝试一下。您可能需要 1 个或 2 个或 3 个反斜杠

在您进行测试时,请执行set -x,以便您可以看到 bash 正在做什么。

【讨论】:

  • 这是我的想法,但这需要我对代码进行大量更改,但毕竟这可能更合乎逻辑!我会让你知道结果如何! :)
  • 它根本不起作用,我尝试使用 FINDVAR+="argument" 向数组添加参数,但脚本只起作用了一半。
  • 将元素附加到数组中:FINDVAR+=( "argument" ) -- 带括号
  • 这不仅是合乎逻辑的,而且是功能性的。正如您所经历的,字符串连接很难做到正确。
  • 哇,谢谢!看起来更好,find 也将参数识别为文件夹,但我认为可以通过将数组与我的文件夹和字符串组合起来来修复它!或者我会在 find 将字符串解释为文件夹路径时遇到同样的错误?
【解决方案2】:

作为一种解决方法,您可以使用 set -f 禁用路径名扩展:

set -f

FINDVAR="/home /ex -type f -name *.sh"
find $FINDVAR

这是可行的,因为 bash 从不尝试将 *.sh 替换为文件名,而是保持原样。

【讨论】:

  • 当我必须在考试中更改内容时,我会尝试这样做。我尝试了很多东西,只是使用了多个 $VARS。祝我好运!
【解决方案3】:

你也可以使用:

FINDVAR="/home /ex -type f -name *.sh"
eval "find $FINDVAR"

【讨论】:

  • 不正当使用 eval。请参阅下面的更好答案。