Linux
我無法使用變數更改腳本中的目錄
我的腳本:
#!/bin/sh _directory1="/home/user/test1" _directory2="test2" cd "${_directory1}/$_directory2" for i in * do echo "$i" done
這是錯誤:
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
我究竟做錯了什麼?
編輯前的原始程式碼:
#!/bin/sh _directory1="~/test1" _directory2="test2" for i in $(cd "${_directory1}/$_directory2") do echo "$i" done
- 波浪號 (
~
) 的行為不像變數。例如,在引號中使用時,它不會擴展到您的主目錄的路徑。在腳本中,使用$HOME
代替波浪號。~
是您可能希望在命令行上使用的“快捷方式”,但$HOME
在腳本中更具描述性。
- 有關詳細資訊,請參閱“為什麼波浪號 (~) 不在雙引號內展開? ”。
cd
不輸出任何你可以循環的東西,所以cd
在命令替換中使用for
不會對你有任何好處。不幸的是,目前還不清楚你希望你的循環實際做什麼,所以我不能給你一個萬無一失的替代實現。帶有您編輯的程式碼:
#!/bin/sh _directory1="/home/user/test1" _directory2="test2" cd "${_directory1}/$_directory2" for i in * do echo "$i" done
此程式碼只會輸出
"./myscript.sh: 6: cd: can't cd to /test2"
如果您拼錯了變數的名稱
_directory1
(並且拼錯的變數為空,並且該/test2
目錄不存在)。然後您再次編輯錯誤消息以說明它輸出
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
這只是意味著該目錄
/home/user/test1/test2
不存在。你沒有提供證據證明這個目錄確實存在,所以我們必須相信你的系統的話。這是一個列出目錄內容的腳本(假設該目錄存在)。該程式碼列印每個文件的完整路徑名。
#!/bin/bash topdir=$HOME/test1 subdir=test2 printf '%s\n' "$topdir/$subdir"/*
或者,
#!/bin/bash topdir=$HOME/test1 subdir=test2 shopt -s nullglob for name in "$topdir/$subdir"/*; do printf '%s\n' "$name" done
nullglob
如果給定的模式不匹配任何東西,shell 選項使循環根本不執行。如果不設置該nullglob
選項,如果 if 不匹配任何內容,則模式將保持未擴展,並且循環會將其用作$name
單次迭代中的值。如果您對隱藏名稱(以字元開頭的文件名)感興趣,您可能還需要設置
dotglob
shell 選項 ( )。shopt -s dotglob``.
或者,不列印每個文件名的完整路徑,
#!/bin/bash topdir=$HOME/test1 subdir=test2 cd "$topdir/$subdir" || exit 1 printf '%s\n' *
如果失敗,
exit 1
將終止腳本。cd
或者,
#!/bin/bash topdir=$HOME/test1 subdir=test2 cd "$topdir/$subdir" || exit 1 shopt -s nullglob for name in *; do printf '%s\n' "$name" done
只列印沒有完整路徑的文件名,而不使用
cd
:#!/bin/bash topdir=$HOME/test1 subdir=test2 shopt -s nullglob for name in "$topdir/$subdir"/*; do printf '%s\n' "$( basename "$name" )" # or: printf '%s\n' "${name##*/}" done
這使用該
basename
實用程序僅提取路徑名的文件名部分。註釋中的替代方法使用標準參數替換,來刪除文件名之前的初始目錄路徑(字面意思是“從${name##*/}
”中刪除與模式匹配的最長前綴字元串)。*/``$name