Shell-Script

附加到文件

  • April 13, 2019

我有一個充滿文件的目錄。我的目標是將文本附加到文件的開頭。每個文件開頭的文本都是相同的。這是我的嘗試

#!/bin/bash                                                                                                                                                    

for file in `find . -type f -executable`;do                                                                                                                                 
   sed '/\#!/bin/bash\/a Hello Word'                                                                                                                                            


done

我的腳本除了崩潰什麼都不做

#!/bin/bash

for file in `find . -type f -executable`;do
    sed '/\#!/bin/bash\/a Hello Word'
fi

done

這個腳本有很多問題。


首先,它不是一個有效的 Bash 腳本,因為你fi沒有對應if的 .


風格上(刪除該fi行之後),我會刪除之前的空行done並在之前添加一個空格do。但這是相對微不足道的。


現在,就最佳實踐而言,您使用反引號來代替命令,而不是推薦的現代形式$(...). 純粹出於歷史原因支持反引號,不建議用於任何新腳本;看:


你有一個健壯性問題,因為你正在循環輸出——find一個非常糟糕的主意,完全沒有必要。您的腳本將中斷任何包含空格或特殊字元的文件名。看:


如果您希望您的腳本是可移植的,您應該盡可能堅持使用 POSIX 指定的功能。特別是POSIX 未指定-executable主要 to 。考慮改用。find``-perm +700

同樣在可移植性方面,在 GNU Sed 中使用“追加”命令到 Sed ( a) 而不使用以下\<newline>序列可以工作,但不是標準的。


您將循環中的file變數for依次設置為每個文件的名稱(假設文件名中沒有特殊字元或空格,這將導致file變數包含不是文件名的內容),但您從未真正使用過該file變數。

您的 Sed 命令沒有提供任何要執行的文件,因此它將嘗試在標準輸入上執行。因此,當您執行腳本時,它只會等待輸入。


您的 Sed 腳本本身是不正確的,這與它缺少要操作的文件名這一事實無關。

如果您/用作正則表達式的分隔符(這是最常見的),則需要反斜杠轉義所有/出現在正則表達式中的實例。將被讀取為正則表達式的命令的唯一部分是/\#!/,其餘部分(以 開頭bin)將被解釋為 Sed 命令。

/ 相反,通常的解決方案是用\/. (我看到你轉義了最後一個斜線,應該轉義。)

**Sed 中有一個鮮為人知的功能,**您可以在這裡使用它來發揮自己的優勢。 任何字元(反斜杠或換行符除外)都可以用作正則表達式分隔符,而不僅僅是使用斜杠。因此,您可以使用等效的地址,而不是/#!\/bin\/bash/用作 Sed 地址\:#!/bin/bash:


現在,如果您已經處理了上述所有要點,您將擁有一個工作腳本。它可能不會做你想讓它做的事情,但它確實會做一些事情。這樣的腳本看起來像這樣:

#!/bin/bash

find . -type f -perm -700 -exec sed '\:#!/bin/bash:a\
Hello World' {} +

這個腳本有什麼作用?它遞歸地在目前目錄中搜尋所有設置了可執行位的文件(對於所有者),並且對於每個這樣的文件,列印整個文件,並在Hello World包含 text 的任何行之後附加文本#!/bin/bash

Sed 實際上並不是為就地編輯文件*而設計的。*它是流編輯器。GNU Sed 將允許您使用開關就地編輯文件-i,但我只會使用標準工具ex進行文件編輯。


但這裡還有一點。如果您想Hello World在 Bash 腳本中添加該行,它實際上不會做任何事情,因為Hello它不是有效的命令名稱。也許您想要的是在 Bash 腳本中列印文本“Hello World”,換句話說,添加echo "Hello World,這可能是有意義的。

現在我們進入了更準確地闡明您的腳本該做什麼的領域。


最終劇本

所以我對這個腳本規範的更準確的陳述是:

  • 該腳本將在目前目錄(或遞歸的任何子目錄)中找到所有為所有者設置了可執行位的正常文件。
  • 對於每個這樣的文件,腳本將檢查文件的第一行是否完全等於字元串#!/bin/bash
  • 僅對於具有此確切第一行的文件,腳本應在文件的第一行之後插入確切的 text echo "Hello World",後跟換行符。(此更改應保存到文件中,而不是列印到標準輸出。)

這是一個匹配這些確切規範的腳本,僅使用 POSIX 工具和功能:

#!/bin/sh

find . -type f -perm -700 -exec sh -c '
 for f
 do
   head -n 1 "$f" | grep -qFx "#!/bin/bash" &&
     printf "%s\n" "1a" "echo \"Hello World\"" . x | ex "$f"
 done
' find-sh {} +

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