正しいファイル拡張子


16

さまざまなファイルタイプの画像が約12000個ありますが、それらはすべて* .jpgという名前に変更されました。

今、私は彼らに適切な拡張子を返したいです、どうすればいいですか


2
再帰的に、または「フラット」ディレクトリに?
ジェイコブVlijm


1
@steeldriverはかなり近いですが、これらのファイルには拡張子がありません。ここでは拡張子が間違っています。
ジェイコブVlijm

1
@JacobVlijmだからこそ、質問を重複としてフラグ付けしませんでした。しかし、答えで提案された方法はここに価値があります、私見
-steeldriver

@steeldriver私は完全に同意します。
ジェイコブVlijm

回答:


23

あなたはbashで比較的簡単にそれを行うことができます:

for f in *jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

これは@ABの答えと同じ考えですが、の代わりにシェルグロブを使用しますfind${f%%.*}その拡張子を除いたファイル名です。コマンドは、それが印刷になり、我々は、その後に使用するファイル名の後にファイルタイプ。これは、スペース、改行などを含む任意のファイル名で機能するはずです。これは、小文字の拡張子を取得するための秘isです。に変換されます。-0file\0grep${type,,}PNGpng

あなたは質問で言っていませんでしたが、これを再帰的にしてサブディレクトリに降りる必要がある場合は、代わりにこれを使用できます:

shopt -s globstar
for f in **/*jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

shopt -s globstarすることができますbashののglobstarオプション有効になります**試合のサブディレクトリを:

グロブスター

設定されている場合、パス名拡張コンテキストで使用されるパターン**は、すべてのファイルと0個以上のディレクトリとサブディレクトリに一致します。パターンの後に/が続く場合、ディレクトリとサブディレクトリのみが一致します。


@ABアップデートを参照してください。**サブディレクトリに再帰することができます。
テルドン

各行の最後にあるセミコロンは冗長ですよね?
水田ランダウ

@PaddyLandauはい、私はそれを1つのライナーとしてテストし、ここに明確にするために改行を追加しました。それらを削除するのを忘れました。あなたが言うように、それらは間違っているのではなく、単に冗長であることに注意してください。
テルドン

素晴らしいですがfile、拡張子を常に指定しているわけではありませんがfoo.bourne-again、たとえばbashファイルをここに変換しているようです!
カンパ

1
@Campaいいえ、もちろん違います。また、バイナリファイル、通常のテキストファイル、perlおよびpythonスクリプトに偽の拡張機能を追加し、リストが続きます。質問は具体的に画像について尋ねていたもので、それらは通常の拡張子と同じ名前を持つ傾向があります。Linuxの拡張機能はオプションであり、例外はほとんどないことを忘れないでください。実際には何もしません。ユーザーがデータを整理するのに役立ちますが、OSはそれらを気にしません。
テルドン

11

以下のスクリプトを使用して、間違って設定された拡張子を.jpg正しい名前に(再帰的に)変更できます。判読できないファイルが見つかった場合、スクリプトの出力で報告します。

スクリプトが使用するimghdr次のタイプを認識するために、モジュールを:rgbgifpbmpgmppmtiffrastxbmjpegbmppngimghdrモジュールの詳細はこちら。リンクで説明されているように、リストはより多くのタイプで拡張できます。

そのまま.jpgで、質問で述べたように、特に拡張子が付いたファイルの名前を変更します。わずかな変更を加えると、任意の拡張子または特定の拡張子のセットを正しい拡張子に変更することができます(または、ここにあるような拡張子なし)。

スクリプト:

#!/usr/bin/env python3
import os
import imghdr
import shutil
import sys

directory = sys.argv[1]

for root, dirs, files in os.walk(directory):
    for name in files:
        file = root+"/"+name
        # find files with the (incorrect) extension to rename
        if name.endswith(".jpg"):
            # find the correct extension
            ftype = imghdr.what(file)
            # rename the file
            if ftype != None:
                shutil.move(file, file.replace("jpg",ftype))
            # in case it can't be determined, mention it in the output
            else:
                print("could not determine: "+file)

使い方

  1. スクリプトを空のファイルにコピーして、名前を付けて保存します rename.py
  2. 次のコマンドで実行します:

    python3 /path/to/rename.py <directory>
    

bashベースのソリューションとは異なり、シンプルで読みやすい+1。
ダビデ

3

注:私のアプローチは複雑すぎるようです。私はあなたの代わりに返事を好むでしょう。


コマンドfileを使用して、ファイルタイプを判別できます。

% file 20050101_14-24-37_330.jpg 
20050101_14-24-37_330.jpg: JPEG image data, EXIF standard 2.2, baseline, precision 8, 1200x1600, frames 3

% file test.jpg
test.jpg: PNG image data, 1192 x 774, 8-bit/color RGBA, non-interlaced

この情報を使用して、ファイルの名前を変更できます。

コマンドを画像に適用する前にテストを行ってください

find . -type f -iname "*.jpg" -print0 | xargs -0 -I{} file -F"<separator>" {} | 
 awk -F " image data" '{print $1}' | 
  awk -F"<separator> " '{
   system("mv \""$1"\" $(dirname \""$1"\")/$(basename -s .jpg \"" $1 "\")."$2)
   }'

% find . -type f -name "*.jpg"
./test.jpg
./sub/20050101_14-24-37_330.jpg

% find . -type f -iname "*.jpg" -print0 | xargs -0 -I{} file -F"<separator>" {} | awk -F " image data" '{print $1}' | awk -F"<separator> " '{system ("mv \""$1"\" $(dirname \""$1"\")/$(basename -s .jpg \"" $1 "\")."$2)}'

% find . -type f -iname "*"    
./test.PNG
./sub/20050101_14-24-37_330.JPEG

これは、ファイル名に改行が含まれているというまれなケースで中断することに注意してください。
テルドン

@terdonはい、私は考えていました。残念ながら、何ができるかわかりません。手伝ってくれますか?
AB

私はawkを使用してこれを適切に行う方法がわかりません。それは仕事にふさわしいツールではありません。使用find -exec bash -c "..."してすべてを実行するか、またはを使用while read -d '' name typeしてファイル名とfile出力を分割し、解析$typeしてファイルタイプを取得します。本当に価値はありません。純粋な(bish)bashでもっと簡単に行う方法については私の答えをご覧ください。
テルドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.