Bash

Bash - 命令替換添加單引號

  • February 17, 2021

在評估重音時,我遇到了 bash 行為的問題。我想用可選的 -name 執行 find:

find -name "*.log"

工作正常,但是當我想從嵌套腳本中獲取 -name 部分時

find `echo "-name \"*.log\""`

它根本行不通。在 bash -x 下執行它顯示,該命令被評估為

find -name '"*.log"'

顯然是因為這個單引號。有什麼辦法可以擺脫它們嗎?最好的祝福。

//請求的作業系統和 bash 版本:Debian, 7.8 wheezy, Bash 4.2.37(1)-release

Bash 沒有在命令中添加單引號。添加您看到的單引號以使顯示的命令成為有效的 bash 語法。如果你看到

find -name '"*.log"'

這意味著 bash 被告知執行此命令:find帶有兩個參數-name"*.log"(雙引號是參數的一部分)。它可以完全像這樣或以其他類似的方式輸入

find -name \"*.log\"
find -name "\"*.log\""
find -name '"*.'log""\"

現在讓我們看看你寫的:

find `echo "-name \"*.log\""`

在子shell中執行的命令是

echo "-name \"*.log\""

它的輸出是

-name "*.log"

這就是參數中的雙引號的來源。當命令替換的輸出被插入到命令行時,它不會被解析為 shell 語法——例如

find `echo '; rm -rf ~'`

不會刪除所有文件,而是;作為第一個參數傳遞給findrm作為第二個,-rf作為第三個和你的主目錄(假設它不包含任何特殊字元)作為第四個。

當變數替換或命令替換在雙引號之外時,變數的值或命令的輸出會發生以下轉換:

  1. 僅用於命令替換:去除尾隨換行符。
  2. 字元串被分解成以空格分隔的片段。(您可以通過設置變數來配置分隔符IFS。)請注意,此轉換的結果是字元串列表
  3. 列表的每個元素都被解釋為萬用字元模式。如果該模式匹配文件,則該元素將替換為匹配文件的列表(這稱為globbing)。如果模式與任何文件都不匹配,則該元素將被單獨保留。

第 2 步將字元串-name "*.log"分成兩部分:-name"*.log". 兩者都不匹配任何文件,因此結果是兩個單詞-name"*.log".

您的意思是find使用參數-name*.log. 您可以通過關閉萬用字元來做到這一點:

set -f
find `echo -name *.log`
set +f

這並不可靠:例如,它不會讓您傳遞包含空格的文件名。一般來說,您不應該嘗試通過將命令的一部分儲存在變數中或在命令中傳遞它們來建構命令。做你正在做的事情的最佳方式取決於你實際想要做的事情。以下是一些一般性建議:

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