Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 5608

古い写真のアルバムをスマホで見るようにしたお話

$
0
0

古い写真のアルバムをスマホで見るようにしたお話

Advent Calendar2018 Elixir(Days15), fukuoka.ex Elixir/Phoenix(Days16) and Vim2(Days15)

IMG_9107.jpeg

Summary

家にあった古いアルバムをデジタル化した話

写真アルバム(左)が誰でもiPhoneで見れるようになった(右)

01.png

ゴールとかとか

Motivation

引っ越すよ
写真アルバムはスペースとるよ
誰もみてないよ
捨てるのもアレだよね

Goal

場所をとらないようにする
気軽に見れるようにする

やってみようと思ったこと

写真をデーター化して Apple's iCloudShared albumsを利用して家族の誰でも気楽に写真を見れるようにする!

Tools

写真整理につかったスクリプトとかとか

Script langdescription
BashScript写真データーの枚数を数える
BashScriptExifデーターを連番にする
ElixirExifデーターを連番にする
Elixir, F#ElixirとF#のちょっとした比較表
F#写真データーのファイル構成を変える
VimVim Manコマンドの設定
Vimvim-refを使ってヘルプを調べる

やったこと

01. 業者さんに写真データーのデジタル化を依頼    
02. 納品データーのチェック                      
03. 重複データーを除く                          
04. 時系列に並び替えてグルーピングする          
05. Apple Shared albums に写真をアップロードする

01 業者さんにデジタル化依頼

ここの作業、楽かと思ってたのですが意外とつらかったです・・・

01 アルバムをページごとにすべてデジカメで写真を撮る
02 アルバムから写真をべりべりはがす
03 アルバムごとの写真の枚数をエクセルに記入する
04 業者さんに発送

01-01 アルバムをページごとにすべてデジカメで写真を撮る

まず控えとして写真アルバムを記録します。写真の並びとか文字情報とかかなり重要なんで絶対に撮っておきます。(単調作業で途中で嫌になってきます)

03.jpg

01-02 アルバムから写真をべりべりはがす

依頼用にベリベリ剥がします。業者さんのコースによっては剥がさなくてもいいコースがあるのですが依頼料金が跳ね上がるので、お金のない callmekoheiは頑張ってベリベリ剥がしましたよ。 写真を傷つけないようにかなり神経を使うので休み休みやるのがおすすめ。心を無にしてマシーンになりませう!

04.jpg

01-03 アルバムごとの写真の枚数をエクセルに記入する

剥がした写真の枚数をエクセルとかに簡単にメモしておきます

05.png

01-04 業者さんに発送

依頼書類とか制約事項誓約書とかを記入して、箱詰めとかして業者さんに送ります

この状態にするのも一苦労やで・・・

10.jpg

02 納品データーのチェック

ここはコーヒー片手にささっとできちゃいます

01 納品データーのファイル構成を確認
02 枚数のチェック
03 以前に控えたアルバムの写真とつきあわせ

02-01 納品データーのファイル構成を確認

callmekoheiDVDでの納品形態を選んだので、外付けのHDDに一旦コピーします。(作業をしやすくするため)

こんな感じのファイル構成でした

納品データー/
├── DVD1
│   ├── _インデックス
│   └── バラ写真
│       ├── BA001
│       |   ├── 色補正前データー
│       |   |   ├── BA001_0001.jpg
│       |   |   ├── BA001_0002.jpg
│       |   |   └── ...
│       |   └── 色補正後データー
│       |       ├── BA001_0001.jpg
│       |       ├── BA001_0002.jpg
│       |       └── ...
│       └── BA010
├── DVD2
│   ├── _インデックス
│   └── バラ写真
│       ├── BA011
│       ├── ...
│       └── BA029
├── DVD3
│   ├── _インデックス
│   └── フィルム
│       ├── SL001
│       |   ├── 色補正前データー
│       |   |   ├── SL001_0001.JPG
│       |   |   ├── SL001_0002.JPG
│       |   |   └── ...
│       |   └── 色補正後データー
│       |       ├── SL001_0001.JPG
│       |       ├── SL001_0002.JPG
│       |       └── ...
│       └── SL050
└── DVD4
    ├── _インデックス
    ├── フィルム
    │   ├── SL051
    │   ├── ...
    │   └── SL090
    └── ポケットフィルム
        ├── PF001
        |   ├── 色補正前データー
        |   |   ├── PF001_0001.JPG
        |   |   ├── PF001_0002.JPG
        |   |   └── ...
        |   └── 色補正後データー
        |       ├── PF001_0001.JPG
        |       ├── PF001_0002.JPG
        |       └── ...
        ├── ...
        └── PF005

02-02 枚数のチェック

下記のコマンドでフォルダ毎に写真データーの枚数を出して、前にエクセルに記入した写真の枚数と照合します

#!/usr/bin/env bashfunction foo (){local folder=$1local path=${HOME}/Desktop/albums/${folder}for d in$(find $path-type d)do

      local cnt=$(ls"$d" | grep-e'jpg'-e'JPG' | wc-l)if[!$cnt=="0"];then
        echo$d" ---> "$cnt\
          | grep-e'BA'-e'SL'-e'PF'\
          | sed-e's|'${HOME}'/Desktop/albums||g'fi

    done}

foo DVD1 | sort
foo DVD2 | sort
foo DVD3 | sort
foo DVD4 | sort

結果

/DVD1/バラ写真/BA001/色補正前のデータ --->  53
/DVD1/バラ写真/BA001/色補正後のデータ --->  53
/DVD1/バラ写真/BA002/色補正前のデータ --->  86
...

02-03 以前に控えたアルバムの写真とつきあわせ

枚数はオーケーだったので、内容を目視でチェックします。ここはまぁだいたいで。

02-04 フォルダ構成を変更する

扱いやすいようにファルダ構成を変えます

色補正後データーに特に問題がなかったのでその分のデーターをまとめて下記のようにします

納品データー/
├── BA
|   ├── BA001
|       ├── BA001_0001.JPG
├── SL
|   ├── SL001
|       ├── SL001_0001.JPG
└── PF
    ├── PF001
        ├── PF001_0001.JPG

03 重複データーのチェック

ここが一番辛かったです・・・。コードを書いて解決できればよかったのですが僕にはそのスキルがなかったです

01 衝(main)となる写真種別を決める
02 重複写真をのぞく(アプリを使用する)
03 重複写真をのぞく(官能評価でおこなう)

03-01 衝(main)となる写真種別を決める

写真種別は今回3種類ありました

写真種別意味callmekoheiの感想
SLフィルムからのデーター結構クリア
PFフィルムからのデーター結構クリア
BA現像プリント写真からのデーター野暮ったい感じ

SL,PFにしかない写真もあれば、BAにしかない写真もありますが、大部分はSL,PFにもあってかつBAにあるという状況でした。

何点か見比べてSL,PFを衝としました。もしかしたらBAのほうが綺麗な(味のある)写真があるかもですがそこはもう機械的にばっさりいきます

SLとBAのデーターの比較(左がSL, 右がBA)

06.png

03-02 重複写真をのぞく(アプリを使用する)

Similar Photos Cleanerというアプリを使ってみたのですが、小一時間やってみたのですが、callmekohei的にはうまく使いこなせず、思うように重複写真をピックアップできなかったです。

かなり迷ったのですが、目視で行くことに決めました!

03-03 重複写真をのぞく(官能評価でおこなう)

目視で重複データーをチェックしました。

まず全ての写真のコンタクトシートを印刷します。コンタクトシートとは写真の一覧表です。左にSL,PFのコンタクトシート、右にBAのコンタクトシートを置いて、SL,PFの写真一枚毎にBAの写真全てに対して重複チェックします。重複写真が一枚の場合もあればそれ以上の場合もあるので最後までBAの写真を確認します

実際の作業様子

07.jpg

トランプの神経衰弱っていうゲームあるじゃないですか?あれの辛いバージョンな感じでしたよ。。。

04 時系列に並び替える、フォルダわけ

重複データーを消し込んだら次は時系列に写真をソートします。具体的にはまずソートする前に簡単なメモを作っておきます例えばこんな感じ

10.png

あとはアルバムに記載されてた文字情報、アルバムの並び、自分の記憶、人の記憶、背景・風景、人の外見等でソートします(具体的にはPhots.appImage > Adjust Date and Time... > Adjustedにて日時を調整してソートします)。それと割と新し目の写真には右下に日時が印字されてるのですが、間違ってることも多々あるので、おかしいなと思ったら盲目的に信じずに確認したほうがいいです

ここまでできたら、あとは写真をグループ分けするだけです!(僕の場合は引越しが多かったので居住地で分けました)

あとアルバムが結構いい加減で違う時間軸が混じってたりしたのですが、背景は意外と情報を与えてくれて整理するのに役立ちました。例えば下記の写真は、同じアルバムに入ってて並んでたのですが、実は違う住居地だったのが襖の模様でわかるという感じです

08.png

05 Apple Shared albums に写真をアップロードする

Apple Shared albumsに追加するのは簡単です。下記の手順で簡単に追加することができます

Shared albums に送りたい写真を選択
> 右クリック
> Shared
> Shared Albums 

しかししかし、ここで問題が発生します

05-01 Shared albums に追加する際の問題

同一日時の写真はランダムに追加される

例えば下記3つのファイルはShared albumsに追加する場合、foo01 -> foo03 -> foo02という並びになってほしいのですが、実際は foo01 -> foo03 -> foo02もしくは foo03 -> foo01 -> foo02となります。どちらになるかはその時次第という感じです

foo01.jpg 1983:01:01 12:11:42
foo02.jpg 1983:10:10 12:11:42
foo03.jpg 1983:01:01 12:11:42

追加順を確実にしたい場合は時刻を変更することでできます。たとえば上記のファイルの場合下記のようにすると確実に並び順を確定できます

foo01.jpg 1983:01:01 00:00:01
foo02.jpg 1983:10:10 00:00:03
foo03.jpg 1983:01:01 00:00:02

時刻を変更する場所は Phots.appImage > Adjust Date and Time... > Adjustedにて変更可能です。ただ全ての写真データーに対してこの操作をするのは辛い感じがしたので、ネットで色々調べたところExifToolというので変更できそうだということがわかりました!

05-02 ExifToolを使ってみる

グーグル検索してみるといろいろなホームページにexiftoolの使い方が載っているのでまずは試してみます

インストール

$ brew install exiftool

日付を変える

// 現状確認
$ exiftool -alldates foo.jpg 
Date/Time Original              : 1987:03:22 00:00:00
Create Date                     : 1987:03:22 16:14:50
Modify Date                     : 1987:03:22 16:14:50

// 日時を変更
$ exiftool -alldates="2999/01/01 00:00:01" foo.jpg 
    1 image files updated

// 変更されているか確認
$ exiftool -alldates foo.jpg
Date/Time Original              : 2999:01:01 00:00:01
Create Date                     : 2999:01:01 00:00:01
Modify Date                     : 2999:01:01 00:00:01

foo.jpgexifデーターが変更されているのが確認できました

さて今回やりたいことはphoto.appでの表示順どおりにshared albumsにも表示したいということです。別の言い方をすると、photos.appではソートキーが第一キーが日時、第二キーがファイル名になっているのが観察されます。この並び順を時刻でするにはどうすればいいかは下記になりそうです

1. 1stソートキーを日時、2ndソートキーをファイル名にしてソートする
2. 時刻をリセット(`00:00:00`)にする
3. ソートした順に1秒ずつ足していく

やりたいことをするための手順はわかったのであとはExiftoolでどのようにするかを調べれば良さそうです。グーグル検索で調べてみました

しかしcallmekoheiのググる力がアレなためうまく見つけることができません

そういえばヘルプあるじゃんと・・・

$ exiftool --help

11.png

ヘルプは出てきたのですが、lessという文書閲覧プログラムをよく知らないためうまく読むことができません

05-03 vimでヘルプを読む

そういえばVimでもヘルプを読むことができるのを思い出しましたよ

# Vimを立ち上げて$ vim
" Manコマンドで読みたいコマンド名を指定する: Man exiftool

色がついてる!

12.png

折りたたみも自由自在!

13.png

もちろん検索も簡単です!

14.png

どんな感じで調べるか?

さてvimを使ってヘルプを読めるようになりましたが、どのように調べればいいのでしょうか?callmekoheiがわからないことは

1. 1stソートキーを日時、2ndソートキーをファイル名にしてソートする
2. 時刻をリセット(00:00:00)にする
3. ソートした順に1秒ずつ足していく

の方法です。ここでは1についての調べ方です。callmekoheiはこんな感じで調べました

まずは、ページ上部をパッと見ます。ふむふむ。
exiftool は options, tag and file と3つの種類の引数をとるんだな

SYNOPSIS
   Reading
          exiftool [OPTIONS] [-TAG...] [--TAG...] FILE...

ソートだからsortで調べてみよっと /\vsort

-sort                            Sort output alphabetically

-sort, --sort
    Sort output by tag description, or by tag name if the -s option is
    used.  When sorting by description, the sort order will depend on

ほむほむ。tagでソートされますよ、と

さらにnをおすと下記の文言が

-fileOrder[-]TAG
        Set file processing order according to the sorted value of the
        specified TAG.  For example, to process files in order of date:

            exiftool -fileOrder DateTimeOriginal DIR

        Additional -fileOrder options may be added for secondary sort
        keys.  Numbers are sorted numerically, and all other values are
        sorted alphabetically.  The sort order may be reversed by
        prefixing the tag name with a "-"(eg. "-fileOrder -createdate").
        Print conversion of the sorted values is disabled with the -n
        option, or a "#" appended to the tag name.  Other formatting
        options (eg. -d) have no effect on the sorted values.  Note that
        the -fileOrder option has a large performance impact since it
        involves an additional processing pass of each file.

callmekoheiは英語苦手なのですが、多分

TAGでソートするよ
追加で -fileOrder 書いたら入れ子のソート(2nd sort)になるかもね

と書いてるので、こんな感じで書けるのがわかります!

$ exiftool \-filename\-fileorder datetimeoriginal \-fileorder filename

vimを使うとこのように自分の調べたいことに集中できるのでヘルプをちゃんと読むことができます!

05-04 BashScriptで連番振りスクリプト書いてみた

かなり四苦八苦しながらBashScriptで書いてみました!

function sortedFilepathList (){#{{{# (その1)ソートされたファイルパスのリストを作成# ExifToolのparamを配列に書くdeclare-aarrFileOrder=(-quiet-fast2-s3-filename-fileorder datetimeoriginal
    -fileorder filename
  )# Date/Time Originalの日時でソートされたファイルパスのリストを変数にいれるecho$(echo*jpg | xargs exiftool "${arrFileOrder[@]}")}#}}}function resetAllTime (){#{{{# (その2)時刻をリセットする# ExifToolのparamを配列に書くdeclare-aarrReset=(-quiet-fast2-s3-d'%Y:%m:%d 00:00:00'-overwrite_original_in_place"-DateTimeOriginal<DateTimeOriginal")# Date/Time Originalの時刻をゼロにリセットするecho*jpg | xargs exiftool "${arrReset[@]}"}#}}}function addOneSecond (){#{{{# (その3)時刻を1秒ずつ進めるlocal baseStr="-quiet -fast2 -s3 -overwrite_original_in_place -DateTimeOriginal+=0:0:"declare-alocal arrFPList=($fpList)local len=$(("${#arrFPList[@]}"-1))for idx in$(seq 0 $len);do
    local fileName="${arrFPList[(($idx))]}"local orderedNumber=$idx
    exiftool $fileName$baseStr$idxdone}#}}}function mainImpl (){#{{{# 写真のあるフォルダに移動local fld=$1cd$fld# (その1)ソートされたファイルパスのリストを作成local fpList=$( sortedFilepathList )# (その2)時刻をリセットする
  resetAllTime

  # (その3)時刻を1秒ずつ進める
  addOneSecond

}#}}}function main (){#{{{# フォルダを指定するlocal fld=$HOME/Desktop/tmptmp

  export-f sortedFilepathList
  export-f resetAllTime
  export-f addOneSecond
  export-f mainImpl
  find $fld-type d | xargs -I % bash -c"mainImpl %"}#}}}

main

結果

$ time bash foo.bash

real    9m2.675s
user    7m19.833s
sys     1m14.571s

これで無事 Apple Shared albumsに意図した順番で登録できました!

おしまい。。。








Others

01. Apple's iCloud Shared albums ってなに?

Appleのホームページによれば下記とのこと

共有アルバムを使えば、
自分で選んだ家族や友人とだけ写真やビデオを共有でき、
相手にも写真、ビデオ、コメントを投稿してもらえます。

---> 写真 App で共有アルバムを使う
---> マイフォトストリームと共有アルバムの制限

// (注)callmekohei のイメージです
アップルが写真データーの保存用に貸してくれるサーバーのこと
iCloudサーバーに保存した写真データーのみ shared albums 用のサーバーにコピーすることができる

こんな感じ( メモ書き )

02.jpg

02. F#でフォルダコピー

02-04 フォルダ構成を変更するにて何度か元データーから上記のファイル構成を作成する必要があったのでF#でコードを書いてみました

openSystem.IOopenSystem.Text.RegularExpressionsletSrcHDD_="/Users/callmekohei/Desktop/albums"letDstHDD_="/Users/callmekohei/tmp4"// コピーしたい写真データーのリストを作成するletsrcJPGs()=["DVD1";"DVD2";"DVD3";"DVD4"]|>List.map(funs->Directory.GetFiles(SrcHDD_+"/"+s,"*",SearchOption.AllDirectories)|>Array.filter(fun(s:string)->s.Contains("色補正後のデータ")))// コピー元のファイルパスとコピー先のファイルパスを組み(タプル)にしたリストを作成するletdstJPGs()=srcJPGs()|>List.map(funarr->arr|>Array.map(funsrcPath->letdestinateFilePath=Regex.Replace(srcPath,@"色補正後のデータ/","")|>funs->Regex.Replace(s,SrcHDD_+@"/DVD\d/バラ写真",DstHDD_+"/BA")|>funs->Regex.Replace(s,SrcHDD_+@"/DVD\d/フイルム",DstHDD_+"/SL")|>funs->Regex.Replace(s,SrcHDD_+@"/DVD\d/ポケットフイルム",DstHDD_+"/PF")|>funs->Regex.Replace(s,".JPG",".jpg")srcPath,destinateFilePath))// もしコピー先のフォルダがなければ作成するletcreateFolderIfnotExists()=dstJPGs()|>List.map(funarr->arr|>Array.map(funtpl->System.IO.Path.GetDirectoryName(tpl|>snd))|>Array.distinct)|>List.iter(funarr->arr|>Array.iter(funfolderPath->ifnot(Directory.Exists(folderPath))thenDirectory.CreateDirectory(folderPath)|>ignore))letmain()=createFolderIfnotExists()dstJPGs()|>Array.concat|>Array.map(fun(src,dst)->async{File.Copy(src,dst)})|>Async.Parallel|>Async.RunSynchronouslymain()

実行はこんな感じ

$ time fsharpi foo.fsx

real    0m39.002s
user    0m5.849s
sys     0m54.564s

03. vim の Man コマンドの設定

Vimの場合

" see ---> :h man.vim" vimrcに書くlet runtime ftplugin/man.vim" foldingを使いたい場合は記述letg:ft_man_folding_enable=1

Neovimの場合

" 特に設定は必要なし" see ---> :h nvim-features > Commands: > :Man" foldingを使いたい場合は vimrc に記述set foldmethod=indent

04. vim-ref でヘルプを調べる

IMG_9298.jpeg

:Man exiftoolとコマンドを調べましたが、例えばpythonのヘルプとかも同じような考え方で:pydoc printとかでできないでしょうか?

vim-refというプラグインを使うとそういったことができます。

使い方はこんな感じ

exiftoolコマンドを調べる

# foo.bash

:Ref man exiftool

or 

# exiftoolという単語の上で K を押す
exiftool 

print関数を調べる

# foo.py:Refpydocprintor# printという単語の上で K を押すprint('foo')

install

vim-refをダウンロードする

$ git clone https://github.com/thinca/vim-ref

vim-refへのパスをセットする

" vimrcset runtimepath+=/path/to/vim-ref

setting

こんな感じ

" see also :h ref.vim , :h ref-man , :h ref-pydocletg:ref_man_cmd='man'letg:ref_pydoc_cmd='python3 -m pydoc'letg:ref_use_vimproc=v:true

注意ポイント

現象: 補完が効かない時がある

:Ref man exif "ここでタブ
"↓:Ref man exif " 補完が効かない

原因: コマンド名がcacheされていない

1. man のコマンド名のキャッシュをつくる
    :Ref man less

2. あらたにコマンドをついかする( $ brew install exiftool )
    $ brew install exiftool

3. キャッシュファイルに exiftoolのコマンド名がないので補完されない
    :Ref man exif...

対策: 下記のコマンドを実行する

:Ref -nocache man exiftool

or

:Ref -updatecache man
:Ref man exiftool

05. F#とElixirのちょっとした比較コード

Elixirのコードをパッとみた感じF#のコードに似てるなと思いました。foo |> barのようにパイプがあるからです。というわけで多分そんなにF#と違わないだろうと思ったので書いてみました! F#と比較しながら書いたので、その時のちょっとしたメモを書いておきます。僕が直感で感じた通り似た感じでした!

basic

file extension 
    fsharp foo.fsx
    elixir foo.exs

binding
    fsharp let foo = 123
    elixir foo = 123

function in pipe
    fsharp 
        "foo" |> fun s ->
    elixir
        "foo" |> fn s -> ... end
        or
        "foo  |> &( &1  )

print

// fsharp"hello"|>stdout.WriteLine[1..5]|>printfn"%A"// hello// [1; 2; 3; 4; 5]
# elixir"hello"|>IO.puts1..5|>IO.inspect# hello# 1..5

iter

["foo";"bar";"baz"]|>List.iterstdout.WriteLine#foo#bar#baz
# elixir["foo","bar","baz"]|>Enum.with_index()|>Enum.each(fn{e,_}->IO.putseend)# foo# bar# baz

tuple

// fsharp("foo","bar","baz")|>fun(_,x,_)->stdout.WriteLinex// bar
# elixir{"foo","bar","baz"}|>elem(1)|>IO.puts# bar

type cast( int -> strings )

// fsharp(1).ToString().GetType()|>stdout.WriteLine// System.String
# elixir ( typeof()がなさそう? )to_string(1)|>is_bitstring|>IO.puts# false

parallel

// fsharplethello1=async{stdout.WriteLine("hello")}letworld1=async{stdout.WriteLine("world")}[hello1;world1]|>Async.Parallel|>Async.RunSynchronously// hello world or world hello
# elixir["hello","world"]|>Task.async_stream(&(IO.puts&1))|>Enum.to_list()# hello world or world hello

module and function ( elixir has no class )

// fsharpmodulefoo=letbarbaz=stdout.WriteLine(baz)foo.bar"aaa"// aaa
# elixirdefmoduleFoododefbar(baz)doIO.puts(baz)endendFoo.bar"aaa"# aaa

06. Elixir で Exif データーを編集してみる

05-04 BashScriptで連番振りスクリプト書いてみたで書いたコードをElixirで書き直してみました!(もっといい方法があるかもしれません・・・・)

defmoduleFoododefsortedFileNameList(fp)doexifToolParam=["-quiet","-fast2","-s3","-filename","-fileorder datetimeoriginal","-fileorder filename"]bashCommand=["-c","cd "<>fp<>" ; echo *jpg | xargs exiftool "<>Enum.join(exifToolParam," ")]System.cmd("bash",bashCommand)|>elem(0)|>(fnx->String.split(x,"\n")end).()|>Enum.drop(-1)enddefresetAllTime(fp)doexifToolParam=["-quiet","-fast2","-s3","-d '%Y:%m:%d 00:00:00'","-overwrite_original_in_place","\"-alldates<alldates\""]bashCommand=["-c","cd "<>fp<>" ; echo *jpg | xargs exiftool "<>Enum.join(exifToolParam," ")]System.cmd("bash",bashCommand)|>elem(0)enddefaddOneSecond(fp)doexifToolParam=["cd "<>fp<>" ; exiftool","-quiet","-fast2","-s3","-overwrite_original_in_place -alldates+=0:0:"]exifToolParam2=Foo.sortedFileNameList(fp)|>Enum.with_index()|>Enum.map(fn{filename,idx}->Enum.join(exifToolParam," ")<>Kernel.inspect(idx)<>" "<>filenameend)exifToolParam2|>Enum.each(&(System.cmd("bash",["-c",&1])))end# 確認用defmyCheck(fp)doexifToolParam=["-quiet","-fast2","-s3","-filename","-datetimeoriginal","-fileorder datetimeoriginal","-fileorder filename"]bashCommand=["-c","cd "<>fp<>" ; echo *jpg | xargs exiftool "<>Enum.join(exifToolParam," ")]System.cmd("bash",bashCommand)|>elem(0)|>(fnx->String.split(x,"\n")end).()|>(fnlst->lst--[""]end).()enddefjpgFolderList(fp)doPath.wildcard(Path.expand(fp)<>"/**/*.jpg")|>Enum.map(&(Path.dirname(&1)))|>Enum.uniqenddefmainImpl(foo)do" sortedFileNameList "|>IO.putsFoo.sortedFileNameList(foo)" resetAllTime "|>IO.putsFoo.resetAllTime(foo)" addOneSecond "|>IO.putsFoo.addOneSecond(foo)" myCheck "|>IO.putsFoo.myCheck(foo)|>Enum.each(&(IO.puts(&1)))end# 写真データーのExifデーターを変更できるようにするために権限を変えるdefchmod644(fld)doSystem.cmd("bash",["-c","cd "<>fld<>" ;  chmod 644 *jpg"])endenddefmoduleMaindo# 写真データーがあるフォルダを指定するbaseFolder="/Users/callmekohei/Desktop/tmptmp"# すべての写真データーのpermissionを644にするFoo.jpgFolderList(baseFolder)|>Task.async_stream(&(Foo.chmod644(&1)),[timeout::infinity,max_concurrency:1000])|>Enum.to_list()# メイン部分を実行Foo.jpgFolderList(baseFolder)|>Task.async_stream(&(Foo.mainImpl(&1)),[timeout::infinity,max_concurrency:1000])|>Enum.to_list()end

実行結果

$ time elixir foo.exs

real    5m48.747s
user    0m2.563s
sys     0m1.753s

ちなみにBashScriptの分はこんな感じ

$ time bash foo.bash

real    9m2.675s
user    7m19.833s
sys     1m14.571s

まえに書いたBashScriptより早くなってますね。パラレルが効いてるのでしょうか?

はまったところ

下記のようにTask.async_streamを2重に使うと扱うデーター数が多くなるとタイムアウトでプログラムが止まってしまいます。今回の場合フォルダ数が5個以上の時にエラーが頻発しました

defaddOneSecond(fp)doexifToolParam2|>Task.async_stream(&(System.cmd("bash",["-c",&1])))|>Enum.to_list()endFoo.jpgFolderList(baseFolder)|>Task.async_stream(&(Foo.mainImpl(&1)),[timeout::infinity,max_concurrency:1000])|>Enum.to_list()

こんな感じのエラーがでます

15.png

(エラー回避)
内側の部分のアシンクを外します

defaddOneSecond(fp)doexifToolParam2|>Enum.each(&(System.cmd("bash",["-c",&1])))end

07. fukuoka ex について

IMG_8367.jpeg

Elixirに興味を持ったのはfukuokaex@piacere_exさんがツイートでばんばんElixirに関しての情報を流してくることがきっかけでした。fukuokaexさんのもくもく会というのに参加させていただいてElixirへの興味が強くなって今回コードを書くに至りました。福岡近辺のひとはもちろんそうでないひともリモートでもくもく会に参加できますので是非参加してみてください!Elixirのこと好きになるかもです!そしてPhoenixに関しても!

fukuoka ex のもくもく会はここを覗いてみてください!
---> fukuokaex もくもく会


Viewing all articles
Browse latest Browse all 5608

Trending Articles