附加到文件
我有一個充滿文件的目錄。我的目標是將文本附加到文件的開頭。每個文件開頭的文本都是相同的。這是我的嘗試
#!/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 {} +