循環變數的輸出顯示的值與預期不同

循環變數的輸出顯示的值與預期不同

想像我目前的工作目錄中有兩個資料夾:back/front/。我試圖進入他們每個人的內心並做一些事情。從下面的簡單腳本:

for dir in */ ; do
    echo "$(dir)"
done

我期待這樣的輸出:

back
front

然而,我得到的是:

back  front
back  front

我不明白。結果是,如果我嘗試cd進入該資料夾:

for dir in */ ; do
    echo "$(dir)"
    cd $(dir)
    echo "$(pwd)"
    cd ..
done

我得到:

back  front
/path/to/back
back  front
/path/to/back

即我從不進入front/。有人可以幫助我理解我做錯了什麼嗎?

答案1

在類似 POSIX 的 shell 中,$(cmd)語法是命令替換,擴展為減去尾隨換行符$(cmd)的輸出。cmd

你想要的是參數擴充:$dir${dir}(此處參數為dir 多變的)。

pwd( print working dictory) 是輸出 1 特殊變數內容的命令,$PWD該變數本身包含目前工作目錄的路徑,因此只要不以換行符號結尾,$(pwd)就會擴展為相同的內容。$PWD$PWD

所以你要:

for dir in */; do 
  (
    printf '%s\n' "$dir"
    cd -- "$dir" &&
      printf '%s\n' "$PWD"
  )
done

或者:

for dir in */; do 
  (
    printf '%s\n' "$dir"
    cd -- "$dir" &&
      pwd
  )
done

也請記住

  • echo不能用於輸出任意數據,請printf改為使用
  • 您通常應該檢查命令的退出狀態。這裡不檢查 的輸出cd意味著cd ..如果第一個失敗,接下來的操作會將您帶到錯誤的位置cd
  • cd最好在子 shell 中執行(使用(...))而不是使用,cd ..因為後者並不總是保證讓您回到初始位置(如果涉及符號連結和/或某些路徑組件已在間隔中重新命名)
  • --當不能保證非選項不以開頭-(或+對於某些命令來說也可能是一個問題)時,必須使用 來將選項與非選項分開。
  • 在類似 POSIX 的 shell 中,參數擴展和命令替換(以及算術擴展)必須用引號引起來,否則它們會經歷您通常不希望的隱式 split+glob(zsh 除外)。

另請注意,在 bash(以及 zsh 以外的其他 POSIX shell)中,當 glob 與任何檔案都不匹配時,它不會展開。

因此如果當前工作目錄不包含任何可以確定為類型的非隱藏文件目錄*/全域模式將擴展到自身*/而不是空列表,您可能會看到一個錯誤,因為cd它無法進入該*/目錄。

在 中zsh,您可以使用Nglob 限定詞for dir in */(N); do...(或for dir in *(N-/); do...避免$dir以 結尾/)。

在 ksh93 中:for dir in ~(N)*/; do....

在 中bash,您可以nullglob暫時全域設定該選項:

shopt -s nullglob
for dir in */; do
  ...
done
shopt -u nullglob

為了完整起見,$(var)語法為Makefile命令使用的 s中的擴充make

在該awk語言中,$是取消引用欄位的一元運算符,您只需用來var引用awk變數。因此,將與or$(var)相同並擴展到第th字段(如果為 0,則擴展到整個記錄)。$var$ varvarvar

rc-like shell 中,與, , ,$(var)相同也可以工作,因為這是傳遞給 的一個元素的列表,因此您取消引用該變量,儘管您通常只使用.$var$ var$ 'var'$ ( 'var' )$var$var

在 TCL 中,$(var)將擴展為鍵名稱為空的數組變數的值var

$ tclsh
% array set {} {foo 1 bar 2}
% puts $(foo)
1

是的,如果在這種情況下, PrintP就沒有多大意義。你可以猜到pwd命令(來自 70 年代中期的 Unix V5)是第一個,$PWD並且邏輯的POSIX 指定的當前工作目錄的處理是後來出現的(在 80 年代初的 ksh 中,其中實際上是(是的,缺少和引號!)pwd的別名,並且在文檔中被縮寫為resent orking目錄)。有一個(當前orking目錄)變數用於相同目的print - $PWD-r$PWDPWDtcsh$cwdcwd

相關內容