我需要获取以字符串 testfile 开头的文件的名称。我还想在同一位置创建一个 XML 文件并将这些文件名写入 XML。
<path>
<dir>
<file>testfile1</file>
</dir>
<dir>
<file>testfile2</file>
</dir>
<path>
答案1
正如@slhck所说,shell 并不是真正适合编写 XML 的工具(尽管它并不像尝试在 shell 中解析 XML 那么糟糕……),但编写一个快速而粗糙的脚本并不太难:
targetdir="/path/to/dir/of/files"
prefix="testfile"
outfile="$targetdir/out.xml"
# Write the opening tag(s):
echo "<path>" >"$outfile"
# Loop through the matching files, writing entries for each one:
for f in "$targetdir/$prefix"*; do
cat <<END_INSERT >>"$outfile"
<dir>
<file>$(basename "$f")</file>
</dir>
END_INSERT
done
# Write the closing tag(s):
echo "</path>" >>"$outfile"
那么上面的方法有什么问题,为什么你要使用真正的 XML 库呢?好吧,考虑一下如果任何文件名恰好包含“<”或“>”(在 unix 文件名中,它们是完全合法的字符)会发生什么情况?正确执行此操作需要使用 HTML 实体对文件名进行编码,并且(据我所知)shell 没有很好的工具来处理这种情况;一个好的 XML 库会自动为您处理这类事情。
关于该脚本的几点说明:首先,请注意,第一次echo
重定向使用“>”,而所有后续对 outfile 的写入都使用“>>”——这是因为“>”在写入之前会清空文件,因此您只需要在第一次写入时这样做。
其次,我将其用于echo
第一次和最后一次写入,但cat
在循环中使用此处文档 - 这只是为了方便,因为echo
对于单行写入来说最容易,但此处文档更容易进行多行写入。您可以轻松地在echo
任何地方使用,或者cat <<
如果您想保持一致,可以在任何地方使用。
第三,我倾向于对包含变量的所有内容使用双引号。这是避免文件名等内容中出现特殊字符(如空格)问题的一种方式。一般来说,我遵循的原则是,除非有特殊原因,否则应该对所有内容使用双引号。XML 遇到特殊字符问题已经够糟糕的了,我不希望在 shell 级别也遇到问题。
答案2
bash shell 可以创建一个 XML 文件,其中包含与某个模式匹配的文件的名称(在本例中为testfile*
):
#!/bin/bash
XML_LIST="$HOME/xml.list"
touch $XML_LIST
#find files matching the regex
find /home/ -name "testfile*" -print0 | xargs -n1 -0 >> /tmp/temp_filelist
echo "<path>" > $XML_LIST
#read list of files from TMP_FILE
#declare array
declare -a FILE_NAMES
#open file for reading to array
exec 10</tmp/temp_filelist
while read LINE <&10; do
FILE_NAMES[$count]=$LINE
if [ "$LINE" != "" ]; then
echo " <dir>" >> $XML_LIST
echo " <file>$LINE</file>" >> $XML_LIST
echo " </dir>" >> $XML_LIST
fi
done
#close temp read file
exec 10>&-
echo "</path>" >> $XML_LIST
echo "done"
将其读入 shell 将会更加复杂,但仍然完全可能。
对于这种脚本,我推荐另一种 Linux 原生语言 Python,它易于学习,并且具有专门的 XML 库,可以用更少的代码行实现上述写入过程以及读取 XML 文件!