[英]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.