拡張子のないファイルにファイル拡張子を自動的に追加する効率的な方法は何ですか?

拡張子のないファイルにファイル拡張子を自動的に追加する効率的な方法は何ですか?

私は今日、ランチ時にディレクトリ内の拡張子のないファイルを見つけて、そのファイルにファイル拡張子を追加するbashスクリプトを作成しました。

複数のフラグとディレクトリの選択、ファイルのコピー、または上書きなどを追加したため、スクリプトは比較的長いですが、実行する作業の主な要旨は、次のように簡単に複製できます。

#recursively find files in current directory that have no extension
for i in $(find . -type f ! -name "*.*"); do
    #guess that extension using file
    extfile=$(file --extension --brief $i)
    #select the first extension in the event file spits something weird (e.g. jpeg/jpe/jfif) 
    extawk=$(echo $extfile | awk -F/ '{print $1}')
    #copy the file to a file appended with the extension guessed from the former commands
    cp -av $i $i.$extawk
done

私の本当のスクリプトでは少しきれいです。ここでコマンドを分割して、なぜこのようにしたのかを説明できるようにしたいと思いました。

私の質問:私が選択した方法でfind組み合わせることがfile最も簡単な方法ではないかもしれません。最高複数のディレクトリにあるさまざまなファイル形式の拡張子を再帰的に推測して追加する方法は?

答え1

for x in $(find …)失敗したスペース(一般)またはワイルドカード(一般的ではない)を含むファイル名find.useを解析しないでください-exec

ジッシュ~のzmvバッチ名の変更に便利です。

必要なタスクを実行するzmvコマンドを作成しましょう。まず、検索パターンを構築してみましょう。

autoload zmv
zmv -C -o -a -n -Q '(*/)#^*.*(.)' …
  • -Cファイルを移動する代わりにコピーします。
  • -o -a-aに渡されましたcp
  • -n何もしないで実行するジョブだけを印刷することを意味します。満足のいくものを削除してください。-vジョブを実行したいが、実行中のジョブも印刷するには、に置き換えます。
  • -Q作るグローバル予選パターンから。
  • (*/)#0個以上のディレクトリと一致します。それを使う# グローバルオペレータextended_globzmvでは常に有効です)。
  • ^*.*名前にaが含まれていないファイルを^一致させるには、glob演算子を使用してください。.
  • (.)一般ファイルの一致を制限するglob修飾子です。
  • 代替テキストに置き換えられます。これは$f元の名前を参照するために使用できます。

zmvすべての代替名は、置換が実行される前に評価され、代替名が既に存在または競合している場合はエラーが表示されます。代替名が元の名前と同じファイルはスキップされます。

それでは、代替テキストを書いてみましょう。私たちはたくさん使うでしょうパラメータ拡張特徴。

  1. file延長をリクエストしてください。$(file --extension --brief -- $f)
  2. 前に1つ追加.、交換の準備:($(echo -n .; file --extension --brief -- $f)
    パラメータ拡張を介して行うこともできます。${:-.$(…)}
  3. 提案された拡張子が複数ある場合(スラッシュで区切られた場合)、最初の拡張子のみが保持されます。${$(echo -n .; file --extension --brief -- $f)%%/*}
  4. 提案された拡張子が空の場合、または???削除されます(.または.???空の文字列で置き換えます)。${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}
  5. 追加された拡張子を$f(元の名前)に追加します。追加した内容が空の場合、ファイルは変更されていません。

結果コマンド:

zmv -C -o -a -n -Q '(*/)#^*.*(.)' '$f${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}'

これは少し難しく、置換を生成するコードを関数に入れてzmv … '$(add_extension $f)'

答え2

私の考えの最も効率的な方法は、ファイルのMIMEタイプをそのファイルを含むデータベースと比較することです/usr/share/mime/globs

  • Linuxではファイル拡張子。与えられた例では、出力は次のようになります。グローバルファイル
application/x-mswinurl:*.url
text/x-mrml:*.mrl
text/x-erlang:*.erl
audio/x-pn-audibleaudio:*.aa
application/x-bzip-compressed-tar:*.tbz2
application/x-netshow-channel:*.nsc
application/x-hdf:*.h4
application/pgp-keys:*.key
text/x-idl:*.idl
text/x-chdr:*.h
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.visio:*.vsd
application/x-hdf:*.h5
video/vnd.mpegurl:*.m4u
  • タイプの例を説明した後、--> Linuxはすべてのファイルを次のように認識text/x-erlangするように指示します。*.アランド拡張子 .erl[glob]を使用すると、これが正しい -->*.erl
  • /etc/magicファイルに含める拡張子を追加できます。

したがって、次のコマンドを実行します。

mimetype -bM file
  • b議論はちょうどあなたに教えてくれますtype-app/extension(短く)

  • M引数は以下を意味します。魔法Linuxはバイトコード、16進数、バイナリ形式のファイルを調べて、ファイルが実際に主張するファイルが正しいかどうかを確認します。

  • 模倣返さない場合は、/jpg/png/webp1 つのタイプのみを返します。file --mime-type file

返品:

image/webp

最後の考え

mimetype次に最適です。バイナリファイルPDF、画像、ビデオなど。これは、バイナリファイルを確認できるため、よりtext plain複雑なものを識別する必要があるため、テキストエディタが他のプログラミング言語を識別できるため、各プログラミング言語に対するユーザーとサーバー言語の助けが必要です。 。

再帰の場合とても良い:

tree -FIi '*.*' | grep -v /$
  • パラメータは、ディレクトリに[スラッシュ]を追加するFことです。例えば→/folderfolder/
  • 引数Iは選択モード*.*[拡張子を持つすべてのファイルを選択するという意味]とは反対なので、その逆は拡張子ではありません。
  • 引数はiツリー出力からスペースを削除することです。
  • grep -vreverseを選択するので、-F/パラメータを追加します。コマンドが先頭にあるので、ディレクトリを削除し、拡張子が/$

詳しくはこちらをご覧ください無言のタイプ

関連情報