Linux
將命令儲存在變數中而不進行評估 - Unix
我正在嘗試將命令儲存在變數中,以便以後可以在遠端伺服器上執行。星號被替換為文件夾名稱並儲存在變數中。我需要該命令與以後使用的星號相同。
腳本:
#!/bin/bash cmd="ls -lrt /client/*/ver* /client/*/*/ver* | grep 299 | tail -1" echo $cmd
輸出:
./script.sh ls -lrt /client/folder299/version_1 /client/ifolder299/ifolder/version_a /client/ifolder300/ifolder1/version_b /client/ifolder301/ifolder2/version_c /client/ifolder302/ifolder3/version_d | grep 299 | tail -1
我試著四處尋找沒有運氣。有人可以幫助我按原樣儲存命令嗎?
該命令不被評估,字元串按原樣儲存在變數中。當您輸出未引用的變數時,它是擴展的萬用字元模式。
cmd="ls -lrt /client/*/ver* /client/*/*/ver* | grep 299 | tail -1"
這是安全的,並將設置
cmd
為文字 stringls -lrt /client/*/ver* /client/*/*/ver* | grep 299 | tail -1
。在這種情況下,在字元串周圍使用雙引號和單引號之間的區別並不重要(但我會使用單引號,因為這是一個靜態字元串)。從某種意義上說,shell 在字元串中沒有任何擴展,這並不重要。如果字元串中有變數或命令替換,shell 會擴展這些,但沒有。當您使用輸出變數的值時
echo $cmd
,通配模式將被擴展(這就是發生的情況),但該命令仍不會執行。要阻止 globbing 模式被擴展,請將變數擴展雙引號為
"$cmd"
. 就個人而言,我會使用printf '%s\n' "$cmd"
列印它的值。請參閱“為什麼 printf 比 echo 更好? ”了解原因。
有關的:
另請注意,由於您正在解析
ls -l
(其本身並不安全)的輸出,然後使用 grepping 查找數字,因此您可以從輸出中的任何位置ls -l
(例如文件大小)中提取該數字。我建議您重新考慮您要解決的更大的問題是什麼,然後提出一個全新的問題。
要從路徑名列表中查找最近修改的正常文件,您可以這樣做
unset newest for pathname in /client/*/ver* /client/*/*/ver*; do if [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then newest=$pathname fi done
這是假設您提到的文件名通配模式擴展為您要檢查的名稱。要另外限制它只允許包含字元串的文件名
299
:unset newest for pathname in /client/*/ver* /client/*/*/ver*; do if [[ "${pathname##*/}" == *299* ]] && [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then newest=$pathname fi done
如果 globbing 模式擴展到您需要遞歸查看的目錄,則使用
bash
:shopt -s globstar unset newest for pathname in /client/*/ver*/** /client/*/*/ver*/**; do if [[ "${pathname##*/}" == *299* ]] && [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then newest=$pathname fi done
通過 SSH 執行的範例:
ssh user@host bash -s -O globstar <<'END_SCRIPT' for pathname in /client/*/ver*/** /client/*/*/ver*/**; do if [[ "${pathname##*/}" == *299* ]] && [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then newest=$pathname fi done printf 'Newest file: %s\n' "$newest" END_SCRIPT