Bash

為什麼在這個 Bash 腳本中不執行 else 分支(for 循環遍歷數組)?

  • January 28, 2022

以下程式碼旨在查找~/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當我擺脫循環時手臂會被執行?如何在保留循環的同時執行我的程式碼?

${TOGOs[@]}表示獲取數組的元素,在空格處將它們分解為單獨的單詞(假設為 default IFS),並將每個單詞解釋為 glob 模式。它與$var標量變數相同,只是它依次列出所有元素。

如果數組中有一個空元素,拆分步驟會將其轉換為 0 個單詞的列表,因此它被有效地刪除。

與往常一樣:在變數和命令替換周圍使用雙引號,除非您知道需要將它們排除在外。要列出數組的元素,正確的語法是"${TOGOs[@]}". 數組訪問“勝過”雙引號:數組的每個元素都放在一個單獨的單詞中。

但是,使用正確的數組列表語法對您沒有幫助,因為您構造數組的方式沒有意義。您將整個輸出find放入單個數組元素中。您無法解析find這種方式的輸出:無法區分作為文件名一部分的換行符和find用於區分文件名的換行符。

而不是解析 的輸出,而是find在 bash 中進行處理,或者使用find -exec …. shopt -s globstar如果您需要,Bash 具有遞歸萬用字元(由 啟用),但是由於您正在使用它,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

引用自:https://unix.stackexchange.com/questions/688362