現在のディレクトリにあるすべてのファイルのMIMEタイプを取得したいのですが。なぜこれが機能しないのですか? OSXまたはLinuxでbashをテストしました。 "file"はファイルが見つからないと不平を言いますが、まったく同じパスで実行すると機能します。
$ find . -type f | xargs -n 1 -I FILE echo $(file --mime-type -b FILE)
ERROR: cannot open './foo.txt' (No such file or directory)
...
$ file --mime-type -b ./foo.txt
text/plain
もちろん、現実の世界では、応答を「エコー」するだけでなく、別のコマンドでMIMEタイプの文字列を使用する必要があります。
これは私が問題を作ることができる最も簡単なものです。私はxargs
ファイル名置換について何かを理解していないと思いますか?
コマンド置換$(file --mime-type -b FILE)
は、xargs
に渡される前にシェルによって実行されるため、必要なものが表示されません。 $(file --mime-type -b FILE)
を引用し、xargsを介してbash -c
に渡します
find . -type f | xargs -n 1 -I FILE bash -c 'echo $(file --mime-type -b FILE)'
ここでxargs
を使用する必要はありません。 find
の_-exec
_スイッチを使用するだけです。
_$ find . -type f -exec file --mime-type -- {} +
_
デフォルトfile
出力
_$ find 8* -type f -exec file --mime-type -- {} + | tail -5
89999/sample10.txt: text/plain
89999/sample2.txt: text/plain
89999/sample4.txt: text/plain
89999/sample6.txt: text/plain
89999/sample9.txt: text/plain
_
_file -b
_出力
_$ find 8* -type f -exec file --mime-type -b -- {} + | head -5
application/x-empty
text/x-Perl
text/plain
text/plain
text/plain
_
これは単なる参考情報ですが、mimetype
と呼ばれる別のコマンドがあり、これを使用して_file --mimetype
_と同じことを行うこともできます。このコマンドは、Fedoraのこのパッケージの一部である_Perl-File-MimeInfo
_であり、同様に機能します。
_$ find 8* -type f -exec mimetype -- {} + | tail -5
89999/sample10.txt: text/plain
89999/sample2.txt: text/plain
89999/sample4.txt: text/plain
89999/sample6.txt: text/plain
89999/sample9.txt: text/plain
_
「エコー以上のものを実行すること」について問い合わせがあり、xargs
を使用しようとしているので、xargs
。
しかし、find
を使用している場合、これは一般的に最良の方法ではありません。代わりにfind
を使用し、次にfind
の_-exec
_スイッチ内でシェルを呼び出して、xargs
を実行させるのではなく、ここでより複雑なことを実行できます。これはより複雑な方法で行われます。
_$ find . -type f -exec sh -c '
cmd1;
cmd2;
file --mime-type -b "$@";
cmd3;
cmd4;
' sh {} \;
_
NOTE:複数の引数を_+
_に渡す_file --mime-type ...
_ターミネーターを使用して、一度に1つずつ渡す_\;
_に切り替えた。
_$ find 8* -type f -exec sh -c '
echo -n "mime-type: ";
file --mime-type -b "$@"
' sh {} \; |& tail -10
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/x-shellscript
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
mime-type: text/plain
_
あなたの問題はシェル拡張についてです。 $()は、引数として渡される前に展開されます。そのまま扱う場合は、一重引用符で囲み、シェルを呼び出します。
また、ファイル名を処理する場合は、print0と0を使用する習慣をつけてください。これらを省略すると、スペース文字を含むファイル名で問題が発生します。
例:
find . -type f -print0 | xargs -0 -n 1 -I FILE bash -c 'echo $(file --mime-type -b FILE)'
あなたの場合、これは次のように簡略化できます:
find . -type f -print0 | xargs -0 -n 1 file --mime-type -b
追加コメント:見つかったすべてのファイル(「xargs -n 1」またはfind + exec)に対してプログラムを呼び出すことは、実際のパフォーマンスのボトルネックになる可能性があります。数千のファイルを含むディレクトリがある場合、数千のプロセスが生成されます。