Bash

如何將命令的輸出分配給 shell 變數?

  • March 23, 2022

我想將表達式的結果(即命令的輸出)分配給一個變數,然後對其進行操作——例如,將它與一個字元串連接,然後回顯它。這是我所擁有的:

#!/bin/bash
cd ~/Desktop;
thefile= ls -t -U | grep -m 1 "Screen Shot";
echo "Most recent screenshot is: "$thefile;

但這會輸出:

Screen Shot 2011-07-03 at 1.55.43 PM.png
Most recent screenshot is: 

因此,看起來它沒有被分配給$thefile,並且在執行時正在列印。

我錯過了什麼?

shell 賦值是一個單詞,等號後沒有空格。因此,您編寫的內容將空值分配給thefile; 此外,由於分配與命令組合在一起,因此它創建thefile了一個環境變數,並且分配對於該特定命令是本地的,即只有呼叫才能ls看到分配的值。

您想擷取命令的輸出,因此需要使用命令替換

thefile=$(ls -t -U | grep -m 1 "Screen Shot")

(一些文獻顯示了另一種語法thefile=ls …`` ;反引號語法等同於美元括號語法,只是在反引號內引用有時很奇怪,所以只需使用$(…).)

關於您的腳本的其他說明:

  • -t(sort by time) 與-U(don’t sort with GNU ls) 結合是沒有意義的;只需使用-t.
  • 與其使用匹配螢幕截圖,不如將grep萬用字元傳遞給ls並用於head擷取第一個文件更清晰:
 thefile=$(ls -td -- *"Screen Shot"* | head -n 1)
  • 解析ls. _ 如果您的文件名包含不可列印的字元,這可能會非常失敗。但是,如果沒有 ,按日期對文件進行排序是很困難ls的,因此如果您知道文件名中沒有不可列印的字元或反斜杠,這是一個可以接受的解決方案。
  • 總是在變數替換周圍使用雙引號,即在這裡寫
 echo "Most recent screenshot is: $thefile"

如果沒有雙引號,變數的值會被重新展開,如果它包含空格或其他特殊字元會造成麻煩。

  • 行尾不需要分號。它們是多餘的但無害的。
  • 在 shell 腳本中,包含set -e. 如果任何命令失敗(通過返回非零狀態),這會告訴 shell 退出。

如果您有 GNU findand sort(特別是如果您執行的是非嵌入式 Linux 或 Cygwin),還有另一種查找最新文件的方法:find列出文件及其日期,然後使用sortand read(這裡假設bashzshfor-d ''讀取NUL 分隔的記錄)來提取最年輕的文件。

IFS=/ read -rd '' ignored thefile < <(
 find -maxdepth 1 -type f -name "*Screen Shot*" -printf "%T@/%p\0" |
   sort -rnz)

如果您願意在 zsh 而不是 bash 中編寫此腳本,則有一種更簡單的方法來擷取最新文件,因為 zsh 具有glob 限定符,不僅允許在名稱上匹配萬用字元,還允許在文件元數據上匹配萬用字元。模式之後的(om[1])部分是 glob 限定符;om通過增加年齡(即按修改時間,最新的在前)對匹配項進行排序,並[1]僅提取第一個匹配項。整個匹配需要放在括號中,因為它在技術上是一個數組,因為 globbing 返回一個文件列表,即使這[1]意味著在這種特殊情況下該列表包含(最多)一個文件。

#!/bin/zsh
set -e
cd ~/Desktop
thefile=(*"Screen Shot"*(om[1]))
print -r "Most recent screenshot is: $thefile"

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