find + grepが一致したときにファイル名を印刷する方法[重複]

find + grepが一致したときにファイル名を印刷する方法[重複]

次の便利な find コマンドは、名前タグの値を出力します。

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \;

問題は、/ tmpの下に複数のxmlファイルがある場合、どのxmlファイルに名前タグがあるのか​​わからないことです。

つまり、この find 構文は Name 値を出力します。

しかし、xmlファイル名はありません。

grepが一致したときにファイル名を印刷する方法を提案してください。

(?<=<Name>).*(?=</Name>)

ベストアンサー1

適切なXMLパーサー(ここで使用するもの)を使用してファイル名の接尾辞がat以下のすべてのXMLファイルからすべてのノードのxmlstarlet値を抽出するには、次のようにします。Name.xml/tmp

find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -v '//Name' -nl {} + 

これは実際にいいえ<Name>開いたタグと対応する閉じるタグは同じ行に</Name>なけれNameばなりませんgrep

xmlstarlet現在処理中のファイル名などの追加情報出力を使用し、ファイルに実際にノードがある場合にのみこれを実行するには、上記のコマンドのName呼び出しxmlstarletを次のように置き換えます。find

xmlstarlet sel -t -i '//Name' -o '### ' -f -o ':' -nl -v '//Name' -nl

これにより、ファイルにノードが含まれている場合にのみ、プレフィックス### とサフィックスが付いたXMLファイルのパス名が出力されます。その後、文書の各ノード値が続きます。:NameName


使用grep:

grepコマンドラインに複数のファイルが指定されている場合は、一致を含むファイルのファイル名が常に出力されます。ファイルが1つだけ渡されると、ファイル名は印刷されません。

実際の一致と一緒にファイル名を常に印刷するには、/dev/null次のファイルをgrepに追加ファイルとして追加します。

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} /dev/null \;

または、通話数を潜在的に減らすには、次の方法をgrep使用しますfind -exec grep ... {} +

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' /dev/null {} +

少なくとも、GNU、OpenBSD、およびFreeBSDは、ファイルが1つだけ提供されていても常にファイル名を印刷するフラグをサポートしgrepます。あなたがそれを使用しているので、おそらくGNUを使用しているでしょう。grep-Hgrep -Pgrep

おすすめ記事