簡體   English   中英

無法使用bash腳本附加到文件

[英]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'在輸入文件中搜索文字( -Fdisabled>true ,並且只有在找到第一個匹配項時,才會停止搜索並打印輸入文件路徑( -l ),具有多個路徑用NUL字符分隔。 -Z )。

  • xargs -0 dirname將輸入(由NUL0 )分割成參數)傳遞給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 -m1grep -qgrep -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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM