「*.mp4
」ファイルのメタデータを読み取り、ファイルのタイムスタンプと動画の作成時間を変更するコマンドを探しています。コマンドは、ファイルの内容に関して読み取り専用である必要があります。つまり、ファイルを前後にハッシュすると、同じ結果が得られます。
状況:スマートフォンの内部ストレージからAndroidのストックツールを使用してSDカードに画像や動画を移動するのを間違えました(「設定」→「ストレージ」→「SDカードにデータを転送」)。残念ながら、これによりすべてのファイルのタイムスタンプがぶつかり、DCIM/
以外のディレクトリが乱雑になりました(画像とビデオもDownload/
、image/
、Pictures/
、およびvideo/
ディレクトリから移動されました)。後から考えて、私がそのようなツールを使用したのはばかげているように見えます(私は通常 Ghost Commander を使用します)が、スペースが足りなくなったときに通知として表示され、とても簡単に見えました。現在、さまざまな画像や動画のタイムスタンプをつなぎ合わせようとしています。
DCIM/100ANDRO/
で画像を並べ替えるために使用した 次のコマンド に相当するビデオを効果的に探しています。
exiv2 -T mv *.JPG
FFmpegのドキュメント をざっと読みましたが、読み取り専用のコマンドやタイムスタンプの出力についての言及はありません。
(残念ながら私の状況では、このアプローチは、私が作成しなかったファイル(Download/
内のものなど)の解決策を提供しません。このファイルについては、入手した日付順にメディアコレクションに表示する必要があります。)
mediainfo
コマンドについて部分的に回答してくれたWarrenに感謝します。
タイムスタンプの復元を実現するコマンドをなんとか構築しました。該当するファイルをループし、ファイルごとにmediainfo
がメタデータを読み取り、grep
とsed
がタイムスタンプを選択してフォーマットし、touch
が適用します。
for file in *.mp4; do touch -t "$(mediainfo "$file" | grep -m 1 'Tagged date' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"; done
「選択とフォーマット」の部分は、間違いなくはるかに短く/優れています。それは私には扱いにくいように見えますが、私は正規表現に堪能ではありません。それにもかかわらず、コマンドは完全に機能しました。私はすべてを正しく引用していると思うので、どのファイル名でも機能するはずです。 mediainfo
が異なる形式を出力する場合は機能しない可能性がありますが、簡単に適応できます。
たとえば、以下は、*.mp4
などのUTC 2013-11-15 11:36:06
ファイルからの出力の形式と、2014-2-23T09:00:00Z
からのmy.mov
のウォーレンの例の形式の両方に正しく一致する正規表現です。 :
's/-/-0/g; s/.*([0-9]{4})-0?([0-9]{2})-0?([0-9]{2})[T ]([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/'
そして、ディストリビューションのリポジトリにないために手動でインストールしなければならなかったmediainfo
を除いて(新しいリリースではパッケージ化されているように見えますが)、かなり移植性が高く、同様の問題。
注:タイムゾーンを確認することを忘れないでください。 GNU info
ページ、touch
、date
、および他のGNU=ユーティリティは設定されている場合はTZ
環境変数、設定されていない場合は「システムのデフォルトルール」使用されるタイムゾーンオフセットを確認するには、次のコマンドを発行します。
date +%:::z
これを変更するには、TZ
環境変数を設定します。
export TZ="UTC0"
動画のタイムスタンプが正しく、正しく表されている場合(つまり、タイムゾーンの時間値が正しい時点を表す場合)、実行する前にdate +%:::z
がタイムスタンプのタイムゾーンに一致するオフセットを出力することを確認する必要がありますtouch -t
これらのファイルを上書きします(上記のとおり)。 stat
を使用して、ファイルをチェックします。これは、(date +%:::z
のように)時間オフセットを示すためです。
そのために MediaInfo を使用できます。
_$ mediainfo my.mov | grep 'Recorded date'
Recorded date : 2014-2-23T09:00:00Z
_
その日付形式からtouch
コマンドに取得するのは、プログラミングの小さな問題です。個人的には、Perlの _Date::Manip
_ モジュールを使用します。上記のフォーマットにほぼ対応できます。この特定の日付形式を理解するには、2桁の月とゼロパディングが必要です。これを修正するには、簡単な正規表現のみが必要です。これは、もちろんPerlでは簡単です。
_$ Perl -M'Date::Manip' -e 'print ParseDate("2014-02-23T09:00:00Z")'
2014022302:00:00
_
印刷されているという事実は、それが解析であることを示しています。 _0
_をドロップすると、ParseDate()
がundef
を返すため、何も出力されないことがわかります。
exiftool:
exiftool "-CreateDate>FileModifyDate" FILES or FOLDERS
必要な値の名前は、ファイル形式やその他の要因によって異なる場合があります。以下を使用してそれらを印刷します。
exiftool -time:all -s FILE
MP4およびほとんどのQuickTimeファイルについては、上記のJamesのアドバイスに従ってください。 AVIファイルの場合、mediainfo
は_Mastered date
_を出力しますが、形式はほとんど解析できません。 ffmpeg
をインストールしてffprobe
(avprobe
とも呼ばれる)を取得し、次を使用します。
for file in *.avi; do touch -t "$(ffprobe "$file" 2>&1 | grep -m 1 'creation_time' | sed -r 's/.*([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}).*/\1\2\3\4\5.\6/')" "$file"; done
grep
にパイプする前にmodに注意してください。これは、ffprobe
がstdoutではなくstderrを使用するためです。