現在のディレクトリと存在しないすべてのサブディレクトリからすべてのxmlファイルを見つける方法から始まる <
最初の行に。
私はこれを試しましたがうまくgrep
いきません:
find . -type f -name '*.xml' | grep "^[^<]" | head -n 1
答え1
すでにいくつかの明確な答えがありますが、代替案を提示しましょう。 XML仕様は非常に厳格で、ファイルはいいえstart withは<
実際にはまったくXMLではありません。
したがって、簡単なアプローチは、ファイルが「有効」であるかどうかをテストすることです。すべてのXMLパーサーはこれを実行できますが、例は次のとおりです。
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
foreach my $filename ( @ARGV ) {
eval { XML::Twig -> new -> parsefile ( $filename ); };
print "File: $filename is not valid XML $@\n" if $@;
}
これは次のように1行にまとめることができます。
perl -MXML::Twig -e 'foreach ( @ARGV ) { eval { XML::Twig -> new -> parsefile ( $_ ) }; print "File: $filename is not valid XML $@\n" if $@;' *.xml
再帰巡回が重要な場合にもFile::Find
便利です。
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use File::Find;
sub check_valid_xml {
#skip any files that don't end in '.xml'
next unless m/\.xml$/;
#validate this file
eval { XML::Twig->new->parsefile($File::Find::name); };
#report errors if detected - parser will abort on invalid XML
if ($@) { print "File $File::Find::name is not valid XML $@"; }
}
find( \&check_valid_xml, "." );
これは感知するどの質問に指定したファイルを含む「無効なXML」です。
答え2
各ファイルの最初の行をgrepして一致するかどうかを印刷するには、xargsとawkを使用できます。
find . -type f -name "*.xml" -print0 | xargs -0 -I{} awk 'NR==1&&!/^</' {}
ファイル名の印刷
find . -type f -name "*.xml" -print0 | xargs -0 -I{} awk 'NR==1&&!/^</{print FILENAME}' {}
答え3
awk
nextfileステートメントをサポートする場合(ほとんどの場合):
find . -name '*.xml' -type f \( -size 0 -print -o -exec awk '
!/^</ {print FILENAME}; {nextfile}' {} + \)
答え4
純粋なバッシュ:
shopt -s globstar
for i in **/*.c;do
read -N 1 h < "$i";
if [[ $h != "<" ]]; then
# echo "found $i";
# do stuff with "$i"
fi;
done
read -N 1
何も分岐/実行せずにファイルから単一の文字を読みます。ファイル名のリストのみが必要な場合は、その-print0
スタイルに簡単に使用できる別の名前を使用してください。