Bash

Bash globbing 和參數傳遞

  • December 16, 2014

我有以下簡化的 bash 腳本

#!/bin/bash

files=("$@")

if [ "X$files" = "X" ]; then
 files=$HOME/print/*.pdf;
fi

for file in "${files[@]}"; do
 ls "$file";
done

如果我將參數(文件名)作為參數傳遞,此腳本將列印正確的文件名。另一方面,如果我不傳遞參數,它將列印

/home/user/print/*.pdf: No such file or directory

為什麼在這種情況下文件名沒有擴展,我該如何解決?請注意,我使用files=("$@")and"${files[@]}"結構是因為我讀到它比通常的“files=$*”更受歡迎。

您分配files標量變數而不是數組變數。

files=$HOME/print/*.pdf

您正在為標量(又名字元串)變數分配一些字元串。/home/highsciguy/print/*.pdf``$files

採用:

files=(~/print/*.pdf)

或者

files=("$HOME"/print/*.pdf)

反而。shell 會將該 globbing 模式擴展為文件路徑列表,並將它們中的每一個分配給$files array的元素。

glob 的擴展是在賦值時完成的。

您不必使用非標準的 sh 功能,您可以通過編寫它來使用您的系統sh而不是bash這裡:

#!/bin/sh -

[ "$#" -gt 0 ] || set -- ~/print/*.pdf

for file do
 ls -d -- "$file"
done

set是分配"$@"位置參數的數組。

另一種方法可能是將通配模式儲存在標量變數中:

files=$HOME/print/*.pdf

$files 並在擴展變數時讓 shell 擴展 glob 。

IFS= # disable word splitting
for file in $files; do ...

在這裡,因為$files沒有引用(通常不應該這樣做),所以它的擴展受分詞(我們在此處禁用)和萬用字元/文件名生成的影響。

因此*.pdf 將擴展為匹配文件的列表。但是,如果$HOME包含萬用字元,它​​們也可以被擴展,這就是為什麼仍然最好使用數組變數。

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