为什么此 Bash 脚本中没有执行“else”分支(for 循环遍历数组)?

为什么此 Bash 脚本中没有执行“else”分支(for 循环遍历数组)?

以下代码旨在查找~/Downloads.我用 运行它. ./script.sh。即使用户提交不完整的名称,它也会找到它们。

#!/usr/bin/bash

echo -e "\nGive me the name of a nonexitent directory and I will look for it in ~/Downloads?\n"

read word

TOGOs=("$(find ~/Downloads -maxdepth 1 -iname "*$word*" -type d -execdir echo {} + | sed 's;./;/home/smith/Downloads/;g')"
"")
for togo in ${TOGOs[@]}
do
  if [[ $togo != "" ]]; then
    echo $togo
    export togo && cd $togo && return 0
  else
    echo "Haven't found it in ~/Downloads ." && cd ~/Downloads #This line does not work
  fi
done

if部分按预期工作 - 当我给它一个名称/子目录名称的一部分时~/Downloads/,但是else当我给它一个不存在的目录时,该块的部分永远不会被执行。else当我摆脱循环时,我可以得到执行的部分,如下所示:

#!/usr/bin/bash

echo -e "\nGive me the name of a nonexitent directory and I will look for it in ~/Downloads?\n"

read word
TOGO=$(find ~/Downloads -maxdepth 1 -iname "*$word*" -type d -execdir echo {} + | sed 's;./;/home/smith/Downloads/;g')

if [[ $TOGO != "" ]]; then
  echo $TOGO
  export TOGO 
  cd $TOGO && return 0
else

  echo "Haven't found it in ~/Downloads." && cd ~/Downloads
fi

为什么else当我摆脱循环时手臂就会被执行?如何在保留循环的同时执行代码?

答案1

${TOGOs[@]}表示获取数组的元素,在空格处将它们分成单独的单词(假设默认为IFS),并将每个单词解释为 glob 模式。它与标量变量相同$var,只是它依次列出所有元素。

如果数组中存在空元素,则拆分步骤会将其变成包含 0 个单词的列表,因此它会被有效删除。

一如既往:在变量和命令替换周围使用双引号除非您知道需要将它们排除在外。要列出数组的元素,正确的语法是"${TOGOs[@]}"。数组访问“胜过”双引号:数组的每个元素都被放入一个单独的单词中。

但是,使用正确的数组列表语法对您没有帮助,因为构造数组的方式没有意义。您将整个输出放入find单个数组元素中。您无法解析这种方式的输出find:无法区分作为文件名一部分的换行符和find用于区分文件名的换行符。

不要解析 的输出find,而是在 bash 中进行处理,或者使用find -exec …. Bash 具有递归通配符(通过shopt -s globstar)如果你需要它,但由于你正在使用它,所以find -maxdepth 1你实际上不需要它,并且find并没有真正做任何有用的事情。

shopt -s dotglob nullglob
TOGOs=(~/Downloads/*$word*/)
if [[ ${#TOGOs[@]} -eq 0 ]]; then
  echo "Haven't found it in ~/Downloads."
fi
for togo in "${TOGOs[@]}"; do
done

相关内容