![如何在 Git Bash 中處理檔案名稱中的空格](https://rvso.com/image/1558675/%E5%A6%82%E4%BD%95%E5%9C%A8%20Git%20Bash%20%E4%B8%AD%E8%99%95%E7%90%86%E6%AA%94%E6%A1%88%E5%90%8D%E7%A8%B1%E4%B8%AD%E7%9A%84%E7%A9%BA%E6%A0%BC.png)
我編寫了以下腳本以在 Windows 7 下的 Git Bash 下運行:
#!/usr/bin/env sh
for logfile in `find -name "*.log" -o -name "*.err" -o -name "*.out"`
do
echo $logfile
grep "api/" "$logfile"
done
問題是當檔案名稱中有空格時 grep 會阻塞。我認為雙引號應該解決這個問題,但它不合作。
有想法嗎?
答案1
解決方案1
最接近的解決方案是使用find
with-print0
並讀取輸出while read …
:
find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
...
繼續使用"$logfile"
引號,就像使用變數時一樣。
解決方案2
另一個解決方案是find
完全不使用,而只grep
在多個文件上運行:
shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out
在這裡,globstar
啟用目錄與**
.nullglob
如果這些檔案副檔名之一不存在,您應該進行設定以防止錯誤。
但這僅適用於有限的文件集,因為您可能會達到命令列參數的最大長度。
為什麼會發生錯誤?
您永遠不應該在( 或,或任何其他輸出帶有空格的檔案名稱的函數)for
的輸出上運行。讀find
ls
本文了解有關為什麼這是一個問題以及可以採取哪些措施來解決該問題的更多資訊。
簡而言之,Bash 透過空格分割參數。假設您有三個檔案 、a
和foo bar
,b
那麼該行將計算為:
for logfile in a foo bar b; do
顯然,Bash 會設定logfile
為a
、foo
、bar
和b
,這不是您想要的。如果您可以手動指定 的輸入for
,則可以將這些檔案名稱括在引號中以解決問題。
為了自動執行此操作,解決方案是用NUL
字元分隔這些檔案名稱(這就是該-print0
選項的作用),然後再次根據該字元分割輸出NUL
(這就是-d ''
in 的作用read
)。