[英]not able to append to a file using bash script
這是我的代碼:
#!/bin/bash -e
dirs=( * )
for f in "${dirs[@]}"
do
while IFS= read -r line; do
case "$line" in
*disabled\>true* )
sed -i '1i "$f"' list.txt;;
esac
done < "$f/config.xml"
done
我沒有使用sed,而是嘗試了echo和printf,但文件list.txt始終是空的。 為什么我無法追加檔案?
echo "$f" >> list.txt;;
printf '%s\n' "$f" >> list.txt;;
測試文件夾下的示例config.xml文件:
<?xml version='1.0' encoding='UTF-8'?>
<project>
<disabled>true</disabled>
</project>
目標:如果test / config.xml中的<disabled>true
,則將“test”打印到list.txt中。
要有效地執行您在問題中嘗試做的事情(需要GNU實用程序):
grep -FZl 'disabled>true' */*.config.xml | xargs -0 dirname | tac > list.txt
這假定你想要:
只有list.txt
記錄的目錄名稱(如果你想要(相對) 文件路徑,只需刪除| xargs -0 dirname
)。
按反向字母順序 - 如果你想升序,只需省略| tac
| tac
部分。
說明:
Glob */*.config.xml
有效地返回當前目錄的任何子目錄中config.xml
文件的(相對)文件路徑。
grep -FZl 'disabled>true'
在輸入文件中搜索文字( -F
) disabled>true
,並且只有在找到第一個匹配項時,才會停止搜索並打印輸入文件路徑( -l
),具有多個路徑用NUL
字符分隔。 ( -Z
)。
xargs -0 dirname
將輸入(由NUL
( 0
)分割成參數)傳遞給dirname
,這導致config.xml
文件包含感興趣字符串的那些目錄的目錄名 。
tac
逆轉了線條
> list.txt
將整個結果寫入文件list.txt
至於你的嘗試問題 :
dirs=( * )
捕獲當前目錄中的任何類型的文件系統項(如果您知道當前目錄只包含目錄 ,那可能不是問題);
dirs=( */ )
將僅限制與目錄的匹配(但請注意匹配將包括尾隨/
)。
sed -i '1i ...' list.txt
的基本問題,正如user2021201在他們的回答中指出的那樣,如果它以空 (零字節)文件開頭,則沒有任何東西被添加到list.txt
:對於空輸入文件,從不執行腳本。
sed
解決方案; 為了逐步附加到文件, >>
是正確的選擇。 另外, sed -i '1i "$f"' list.txt
,正如Rany Albeg Wein在對該問題的評論中指出的那樣,嘗試在單引號字符串中擴展$f
,這將無效 - 相反, 文字 "$f"
將寫入文件(假設文件非空)。
此外,通過使用1i
(在第1行之前插入),每個新條目將被添加為第一行,從而有效地產生包含匹配目錄的list.txt
。 以相反的順序。
如果不退出while
循環一旦找到匹配,你不僅無謂地處理文件中剩余的線路,但也風險手頭多次添加目錄list.txt
在事件中搜索字符串更多的發現超過1行。
正如user2021201在他們的回答中指出的那樣,你的方法是低效的,因為(a)可以使用多級glob,例如*/*.config.xml
來代替循環,以及(b)因為grep
可以用來更有效地搜索每個文件的內容並在找到第一個匹配后退出(使用grep -m1
或grep -q
或grep -l
,所有語義略有不同)。
首先,請注意您的sed表達式不適用於空文件。 我修改了代碼,它滿足了你的目標:
#!/bin/bash -e
for f in */config.xml # process all config.xml files
do
while IFS= read -r line; do
case "$line" in
*disabled\>true* )
# obtain directory name of the file
# and append it to list.txt
dirname "$f" >> list.txt
esac
done < "$f"
done
但是,我寧願使用以下方法:
#!/bin/bash -e
for f in */config.xml
do
# -m1 - exit at first occurence for performance
if grep -m1 'disabled>true' "$f" >/dev/null; then
dirname "$f" >> list.txt
fi
done
甚至更簡單:
grep -l 'disabled>true' */config.xml | cut -d/ -f1 > list.txt
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.