无法使用 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

我也尝试了 echo 和 printf 而不是 sed,但是文件 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。

首先,请注意您的 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

要有效地完成您在问题中尝试要做的事情,请使用(需要 GNU 实用程序):

grep -FZl 'disabled>true' */*.config.xml | xargs -0 dirname | tac > list.txt

假设您想要:

  • 只有目录记录在list.txt中的名称(如果你想要(相对),只需删除| xargs -0 dirname文件 路径).

  • in reverse字母顺序-如果你想要升序,只需省略| tac部分。

解释:

  • Glob */*.config.xml 高效 returns 当前目录的任何子目录中 config.xml 个文件的(相对)文件路径。

  • grep -FZl 'disabled>true' 在输入文件中搜索字面值 (-F) disabled>true,并且只有当 first 找到匹配项,停止搜索并打印输入文件路径 (-l),多个路径用 NUL 个字符分隔。 (-Z).

  • xargs -0 dirname 将输入按 NUL (0) 拆分为参数传递给 dirname,结果是 目录名称 config.xml 文件包含感兴趣的字符串的那些目录。

  • tac 反转行

  • > list.txt 将整体结果写入文件 list.txt


至于你的尝试遇到的问题

  • dirs=( * ) 捕获当前目录中 任何类型 的文件系统项(如果您知道当前目录仅包含 目录,这可能不是问题);
    dirs=( */ ) 会将匹配仅限于目录(但请注意,匹配将包括结尾的 /)。

  • sed -i '1i ...' list.txtuser2021201 points out in 的根本问题是 什么都没有添加到 list.txt 如果它开始时是一个 empty(零字节)文件:根本不会为空输入文件执行脚本。

    • 这个问题没有简单的单一命令 sed 解决方案;对于 增量添加到文件,>> 是正确的选择。
  • 此外,sed -i '1i "$f"' list.txt,正如 Rany Albeg Wein 在对该问题的评论中指出的那样,试图在 中扩展 $f -quoted 字符串,这将不起作用 - 相反,literal "$f" 将被写入文件(假设文件非空)。
    此外,通过使用 1i(在第一行之前插入),每个新条目都将添加为 first 行,有效地导致 list.txt 包含匹配的目录.按反向顺序。

  • 如果找到匹配项后不退出 while 循环,您不仅会不必要地处理文件中的剩余行,而且还会冒添加手头目录的风险 多次 list.txt 如果在超过 1 行中找到搜索字符串。

  • user2021201 points out in 一样,您的方法效率低下,因为 (a) 可以使用 */*.config.xml 等多级 glob 代替循环,并且 (b ) 因为 grep 可用于更有效地搜索每个文件的内容,并在找到第一个匹配项后退出(使用 grep -m1grep -qgrep -l,都略有不同的语义)。