繁体   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