質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

terminal

Terminalは、Apple社のmacOSに標準で付属しているUNIX端末エミュレータ。UNIXコマンドによってMacの操作および設定を行うことができます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

600閲覧

日付が連続しているファイルの欠番を一日前のファイルを用いて埋めたい

momokoko

総合スコア38

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

terminal

Terminalは、Apple社のmacOSに標準で付属しているUNIX端末エミュレータ。UNIXコマンドによってMacの操作および設定を行うことができます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/06/10 16:27

ディレクトリ構造

$ ls -1 cham-arayaminami-high/2020年02月23日01時02分.jpg 2020年02月24日01時02分.jpg 2020年02月26日01時02分.jpg 2020年02月27日01時02分.jpg ~ 2020年06月10日12時06分.jpg

抜けている日付を前の日の画像を複製し、補完したいです。
また、Exif情報の撮影された日時(DateTimeOriginal)を前の日のものではなく補完後のものと合わせたいです。
抜けている日付は数日間あるものをあります。

目的が達成できれば、シェルスクリプトでもpythonでも構いません。
ネットでも探しても似たような記事すら検索にかからず困っております。
ご教授頂けたら嬉しいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hidezzz

2020/06/10 16:40

補完して作成したファイルの時刻部分はどうなれば良いですか?(00時00分で良いですか?)
momokoko

2020/06/10 16:42

質問ありがとうございます! 時刻は問いません。
guest

回答2

0

ベストアンサー

python版を作って見ました(file_comp.py)。
外部ツールとしてExiftoolを必要とします。
同じ日のファイルが2つ以上存在するとエラーになります。

python

1import argparse 2import pathlib 3import pandas as pd 4from shutil import copyfile 5 6FILENAME_FORMAT = "%Y年%m月%d日%H時%M分.jpg" 7 8 9def update_exif(filename, exif_datetime): 10 import subprocess 11 12 args = [ 13 "exiftool", 14 "-overwrite_original", 15 "-DateTimeOriginal={}".format( 16 exif_datetime.strftime("%Y:%m:%d %H:%M:%S") 17 ), 18 filename, 19 ] 20 subprocess.Popen(args, stdout=subprocess.DEVNULL) 21 22 23def main(): 24 parser = argparse.ArgumentParser() 25 parser.add_argument("dirname") 26 args = parser.parse_args() 27 28 # ファイルリストを作成 29 p = pathlib.Path(args.dirname) 30 filenames = [] 31 for pathname in p.iterdir(): 32 try: 33 pd.to_datetime(pathname.name, format=FILENAME_FORMAT) 34 filenames.append(pathname.name) 35 except ValueError: 36 pass 37 filenames.sort() 38 39 # 日付をインデックスに持つDataFrameを作成 40 df = pd.DataFrame({"src_filename": filenames}) 41 df["datetime"] = pd.to_datetime(filenames, format=FILENAME_FORMAT) 42 df.index = pd.DatetimeIndex(df.datetime.dt.date) 43 df.index.name = "date" 44 45 # 1日でリサンプリング 46 df = df.asfreq(freq="1D") 47 48 # 存在しない日付は前の日のファイルを複製 49 df.src_filename.fillna(method="ffill", inplace=True) 50 51 # EXIFに埋め込む時刻は日付+00:00:00 52 df["exif_datetime"] = df.datetime 53 df.exif_datetime.fillna(df.index.to_series(), inplace=True) 54 55 # 出力するファイル名を作成 56 df["dst_filename"] = df.exif_datetime.dt.strftime(FILENAME_FORMAT) 57 58 df_target = df[df.datetime.isnull()] 59 # デバッグ用 60 print(df_target[["src_filename", "dst_filename", "exif_datetime"]]) 61 62 # 処理対象のみ抽出して複製 63 for _, row in df_target.iterrows(): 64 src = p / row.src_filename 65 dst = p / row.dst_filename 66 copyfile(src, dst) 67 update_exif(dst, row.exif_datetime) 68 69 70if __name__ == "__main__": 71 main()

実行は引数にディレクトリを渡します。
実行すると新たに作成したファイルの一覧が表示されます。

terminal

1$ tree cham-arayaminami-high/ 2cham-arayaminami-high/ 3├── 2020年02月21日01時02分.jpg 4├── 2020年02月23日02時02分.jpg 5└── 2020年03月01日01時02分.jpg 6 7$ python file_comp.py cham-arayaminami-high/ 8 src_filename dst_filename exif_datetime 9date 102020-02-22 2020年02月21日01時02分.jpg 2020年02月22日00時00分.jpg 2020-02-22 112020-02-24 2020年02月23日02時02分.jpg 2020年02月24日00時00分.jpg 2020-02-24 122020-02-25 2020年02月23日02時02分.jpg 2020年02月25日00時00分.jpg 2020-02-25 132020-02-26 2020年02月23日02時02分.jpg 2020年02月26日00時00分.jpg 2020-02-26 142020-02-27 2020年02月23日02時02分.jpg 2020年02月27日00時00分.jpg 2020-02-27 152020-02-28 2020年02月23日02時02分.jpg 2020年02月28日00時00分.jpg 2020-02-28 162020-02-29 2020年02月23日02時02分.jpg 2020年02月29日00時00分.jpg 2020-02-29 17 18$ tree cham-arayaminami-high/ 19cham-arayaminami-high/ 20├── 2020年02月21日01時02分.jpg 21├── 2020年02月22日00時00分.jpg 22├── 2020年02月23日02時02分.jpg 23├── 2020年02月24日00時00分.jpg 24├── 2020年02月25日00時00分.jpg 25├── 2020年02月26日00時00分.jpg 26├── 2020年02月27日00時00分.jpg 27├── 2020年02月28日00時00分.jpg 28├── 2020年02月29日00時00分.jpg 29└── 2020年03月01日01時02分.jpg 30 31$ exiftool -n -DateTimeOriginal cham-arayaminami-high/*.jpg 32======== cham-arayaminami-high/2020年02月21日01時02分.jpg 33Date/Time Original : 2020:06:10 14:35:34 34======== cham-arayaminami-high/2020年02月22日00時00分.jpg 35Date/Time Original : 2020:02:22 00:00:00 36======== cham-arayaminami-high/2020年02月23日02時02分.jpg 37Date/Time Original : 2020:06:10 14:35:34 38======== cham-arayaminami-high/2020年02月24日00時00分.jpg 39Date/Time Original : 2020:02:24 00:00:00 40======== cham-arayaminami-high/2020年02月25日00時00分.jpg 41Date/Time Original : 2020:02:25 00:00:00 42======== cham-arayaminami-high/2020年02月26日00時00分.jpg 43Date/Time Original : 2020:02:26 00:00:00 44======== cham-arayaminami-high/2020年02月27日00時00分.jpg 45Date/Time Original : 2020:02:27 00:00:00 46======== cham-arayaminami-high/2020年02月28日00時00分.jpg 47Date/Time Original : 2020:02:28 00:00:00 48======== cham-arayaminami-high/2020年02月29日00時00分.jpg 49Date/Time Original : 2020:02:29 00:00:00 50======== cham-arayaminami-high/2020年03月01日01時02分.jpg 51Date/Time Original : 2020:06:10 14:35:34 52 10 image files read

投稿2020/06/10 23:30

yymmt

総合スコア1615

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momokoko

2020/06/11 19:13

回答ありがとうございます! 無事、ファイルが前日のもので複製されました! 追加の質問になってしまい恐縮ですが、cham-arayaminami-highのようなディレクトリが70個ほどありfor文などで回して処理したいと考えていました。 「./実行ファイル 引数(ディレクトリ)」という形で処理するのが初めてで、繰り返し処理ができるのかもよくわかっておりません。 ググっても見つけることができなかったのですが、何かいい方法があったら教えていただきたいです。
yymmt

2020/06/11 21:48

findコマンドを使うのはどうでしょうか? 例えばあるディレクトリA以下に A ├── 対象ディレクトリ1/ ├── 対象ディレクトリ2/ └── 対象ディレクトリ3/ のような構造を持つ場合は、findコマンドで次のように一括処理できます。 find A -type d -exec python file_comp.py {} \;
momokoko

2020/06/15 03:00

返信がおそくなりすみません。 無事できました! ありがとうございました!
guest

0

AWKスクリプトを作ってみました。
重要な注意:必ずあらかじめ全体のバックアップを取ってください。
LinuxMint19.3(Ubuntu18.04LTSほぼ同等)で動作確認してます。
Exiftoolが別途必要です。
dateコマンドはGNU版が必要です。(Macの場合最初から入ってるdateだと動かないかも)

AWK

1#! /usr/bin/awk -f 2{ 3 # ファイル名から日付year,month,dayを取り出す。 4 year = substr( $0, 1, 4 ); 5 month = substr( $0, 6, 2 ); 6 day = substr( $0, 9, 2 ); 7 8 # 年月日からシリアル秒serialsecを求める。 9 "date -d " year "-" month "-" day " +%s" | getline serialsec; 10 11 # 連想配列(シリアル秒→ファイル名)を作る。 12 days[ serialsec ] = $0; 13 14 # 開始日付と終了日付を求める。 15 if ( NR == 1 ) { 16 start = serialsec; 17 end = serialsec; 18 } 19 else { 20 if ( start > serialsec ) { 21 start = serialsec; 22 } 23 if ( end < serialsec ) { 24 end = serialsec; 25 } 26 } 27} 28END { 29 30 # 開始日付から終了日付までループする 31 for ( t = start ; t <= end ; t += 86400 ) { 32 33 # 画像ファイルが存在する? 34 if ( t in days ) { 35 # 画像ファイルのファイル名を覚えておく。(抜けてる日付位置にはこのファイルをコピーする) 36 print "# " days[ t ]; 37 last = days[ t ]; 38 } 39 else { 40 # コピーを実行するコマンド文字列を出力する。 41 "date -d @" t " +'%Y年%m月%d日00時00分.jpg'" | getline fname; 42 print "cp -p " last " " fname 43 # Exifを書き換えるコマンドをするコマンド文字列を出力する。 44 "date -d @" t " +'%Y-%m-%d 00:00:00'" | getline date; 45 print "exiftool -DateTimeOriginal='" date "' " fname 46 } 47 } 48} 49

terminal

1 2(元ファイルとAWKスクリプト) 3$ ls -l 4-rw-r--r-- 1 hidezzz hidezzz 3555099 4月 26 2016 2016年04月26日12時00分.jpg 5-rw-r--r-- 1 hidezzz hidezzz 3381213 4月 27 2016 2016年04月27日12時00分.jpg 6-rw-r--r-- 1 hidezzz hidezzz 3474408 4月 29 2016 2016年04月29日12時00分.jpg 7-rwxrwxr-x 1 hidezzz hidezzz 1352 6月 11 03:44 umeume.awk* 8 9(実行されるコマンドの確認(まだこのコマンドでは実行されません)) 10$ ls -1 *.jpg | ./umeume.awk 11# 2016年04月26日12時00分.jpg 12# 2016年04月27日12時00分.jpg 13cp -p 2016年04月27日12時00分.jpg 2016年04月28日00時00分.jpg 14exiftool -DateTimeOriginal='2016-04-28 00:00:00' 2016年04月28日00時00分.jpg 15# 2016年04月29日12時00分.jpg 16 17(末尾に「| sh」を付けて上記で表示されているコマンドを実際に実行) 18$ ls -1 *.jpg | ./umeume.awk | sh 19Warning: [minor] Overlapping MakerNotes values - 2016年04月28日00時00分.jpg 20 1 image files updated 21 22(補完されたファイルの確認) 23$ ls -l *.jpg* 24-rw-r--r-- 1 hidezzz hidezzz 3555099 4月 26 2016 2016年04月26日12時00分.jpg 25-rw-r--r-- 1 hidezzz hidezzz 3381213 4月 27 2016 2016年04月27日12時00分.jpg 26-rw-r--r-- 1 hidezzz hidezzz 3381219 6月 11 03:49 2016年04月28日00時00分.jpg 27-rw-r--r-- 1 hidezzz hidezzz 3381213 4月 27 2016 2016年04月28日00時00分.jpg_original 28-rw-r--r-- 1 hidezzz hidezzz 3474408 4月 29 2016 2016年04月29日12時00分.jpg 29 30(Exif情報の確認) 31$ exiftool -n -DateTimeOriginal 2016年04月28日00時00分.jpg* 32======== 2016年04月28日00時00分.jpg 33Date/Time Original : 2016:04:28 00:00:00 34======== 2016年04月28日00時00分.jpg_original 35Date/Time Original : 2016:04:26 17:28:24 36 2 image files read

投稿2020/06/10 19:27

hidezzz

総合スコア1248

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momokoko

2020/06/10 23:48

回答ありがとうございます! 念のため確認なのですが、全体のバックアップとはmac全体でしょうか? 昨日、apt-getを用いてExiftoolをインストールする記事を見かけまして、OSを破損する可能性がなくなないのかなと思って質問しています。 先程、brew install exiftoolでインストールできる記事を見つけたのでbrewを用いてインストールをします。 バックアップはどの範囲なのかをご教授ください!
hidezzz

2020/06/11 01:05 編集

処理に失敗すると最悪の場合画像ファイル群のあるディレクトリが元に戻せなくなるかもしれないのであらかじめバックアップをしてください。 上記「$ ls -1 *.jpg | ./umeume.awk 」の段階で実行するコマンドが標準出力に表示されるので、それを見て何が行われるかを理解してから次の「| sh」を付けた実行をするようにしてください。 ※追記:実行されるコマンドは空いた日付のファイルを補完するための「cp」コマンドと、ファイル中のExif情報を書き換える「exiftool」コマンドの2つです。 今回のAWKスクリプトをrootで実行しない限りシステムを破壊することは無いとは思います。 rootでもapt-getやbrewで、信頼できるパッケージを入れる限りはまあ問題はないと思います。 一般論的な話ですが、今回の作業にかかわらず失って困るものに関しては定期的にバックアップは取るべきだと思います。どんな結果になって私は責任を追うことは出来ません。 Macで実行するのであれば、元から入っている「date」コマンドは使わずに brew install coreutils でインストールされる「gdate」コマンド(GNU版のdateコマンド)を使ってください。 (AWKスクリプト中に3箇所使われている「date」を「gdate」に修正してから実行してください。
momokoko

2020/06/11 18:59

バックアップを取って実行しました! 下記のように書き換えました。 "gdate -d " year "-" month "-" day " +%s" | getline serialsec; "gdate -d @" t " +'%Y年%m月%d日00時00分.jpg'" | getline fname; "gdate -d @" t " +'%Y-%m-%d 00:00:00'" | getline date; 実行しましたがエラーが出てしまいました。 ls -1 *.jpg | ./umeume.awk gdate: invalid date ‘2020-\271\264-2\346’ gdate: invalid date ‘2020-\271\264-4\346’ gdate: invalid date ‘2020-\271\264-5\346’ gdate: invalid date ‘2020-\271\264-6\346’ # 2020年06月09日01時06分.jpg
hidezzz

2020/06/12 00:39

マルチバイト文字(日本語文字)が認識してないような気がします。 $ export LANG=ja_JP $ export LANG=ja_JP.UTF-8 あたりを実行してからスクリプトを実行するとどうなりますか? 別の方の回答で解決しているようなので時間が空いたときにでもどうぞ
momokoko

2020/06/15 03:01

返信ありがとうございます! 返信おそくなりました。 いま仕事中でできませんが、また時間ができたときにやってみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問