我有一个包含约 10K XML 文件的文件夹。他们每个人看起来都是这样的:
...
<object>
<name>Cat</name>
</object>
<object>
<name>Cow</name>
</object>
...
包括name
人、猫、狗、牛……我想挑选出唯一带有猫和/或狗的 xml 文件。我怎样才能做到这一点?
答案1
要从像您这样的 XML 文档中的节点中获取所有Cat
or值,您可以像这样使用:Dog
name
xmlstarlet
xmlstarlet sel -t -v '//object/name[text() = "Cat" or text() = "Dog"]' file.xml
如果文档中存在单词 和 作为节点子节点的值,则这将生成单词Cat
和作为输出。如果存在其他节点不是节点的子节点,或者某些节点具有属性等,则此操作将很难正确执行。Dog
object
name
grep
name
object
name
不幸的是,xmlstarlet
如果在 XML 输入文件中找不到任何内容,则不会以非零退出状态退出,因此我们需要grep
在末尾添加 a 来检查是否有任何输出(这将是在下一步中使用):
xmlstarlet sel -t -v '//object/name[text() = "Cat" or text() = "Dog"]' file.xml | grep '.'
然后我们可以在所有 10k 个文件上运行它find
:
find . -type f -name '*.xml' -exec sh -c '
xmlstarlet sel -t -v "//object/name[text() = \"Cat\" or text() = \"Dog\"]" "$1" |
grep -q "."' sh {} ';' -print
这将首先找到当前目录中或当前目录下名称以.xml
.对于每个这样的文件,xmlstarlet
运行以从正确的 XML 节点中提取Cat
和字符串,并用于检查是否找到任何内容。使用其选项运行会使实用程序安静,但它将以适当的退出状态退出,具体取决于它是否匹配任何内容。Dog
grep
xmlstarlet
grep
-q
如果grep
找到任何内容,find
则打印包含该数据的文件的路径名。
答案2
以下代码基于GNU grep
正如你所说,所有文件都是这样,所以你可以使用 grep
对于猫或狗,使用
grep -l '<name>\(Cat\|Dog\)</name>' *
如果猫和狗都在场,请使用
grep -l '<name>Cat</name>' * | xargs grep -l '<name>Dog</name>'
如果您想要不区分大小写的搜索,请-i
向 grep 添加选项
-l
- 此选项将仅打印匹配的文件名
使用普通的正则表达式,字符(
,|
和)
需要转义,所以我已经转义了它们
答案3
如果你有许多文件考虑使用索引器工具,如 Beagle、Tracker、glick 或类似工具。
例子:
$ glimpseindex -H . MyDir
$ glimpse -l -H . 'cat;dog'
获取包含cad和dog的文件