(この記事は「fukuoka.ex Elixir/Phoenix Advent Calendar 2018」の15日目です)
昨日は@zacky1972さんの
ZEAM開発ログ2018年総集編その2: Elixir 研究構想についてふりかえる(後編)
でした!
この記事は「古い写真のアルバムをスマホで見るようにしたお話」の後日談です
Summary
Exif
データーを編集するBashScript
のコードをElixir
で書いてみました
実行時間が約半分になったよ
実行時間の比較
Elixir
$ 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
Motivation
「古い写真のアルバムをスマホで見るようにしたお話」で写真を整理するためにBashScript
を書いたのですが結構遅かったので、もう少し早くならないかな〜と思ったので、、、
ってElixirってなに?
なんでしょう? callmekohei
もよくはElixir
を知りません(すいませんっ)
今時点callmekohei
がElixir
について知っていることは
- スクリプト言語だよ(手軽に書けるよ)
- 左から右にるるるる〜という言語だよ(
|>
があるよ) -
F#
という言語にすごく似てるよ
ぐらいですっ
ってなんでElixir?
しょっちゅうTwitter
のタイムラインに流れてくるからです
@piacere_ex さんというかたをフォローしたら怒涛のごとくElixir
の情報が流れてきました(笑)
もくもく会
というのがあって先日参加させていただいたらElixir
に興味が出てきました!
fukuoka ex のもくもく会はここを覗いてみてください!
---> fukuokaex もくもく会
Elixir で Exif データーを編集してみる
F#を横目にElixirで「こんにちは世界」 でElixir
の「こんにちは世界」ができたのでさっそく実際にコード書いてみました!
古い写真のアルバムをスマホで見るようにしたお話 05-05 BashScriptで連番振りスクリプト書いてみた で書いたBashScript
のコードをElixir
で書き直してみました!(もっといい方法があるかもしれません・・・・)
defmodule Foo do
def sortedFileNameList( fp ) do
exifToolParam = [
"-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)
|> ( fn x -> String.split(x ,"\n") end ).()
|> Enum.drop( -1 )
end
def resetAllTime( fp ) do
exifToolParam = [
"-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)
end
def addOneSecond( fp ) do
exifToolParam = [
"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) <> " " <> filename
end )
exifToolParam2
|> Enum.each( &( System.cmd("bash",["-c" , &1]) ))
end
# 確認用
def myCheck( fp ) do
exifToolParam = [
"-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)
|> ( fn x -> String.split(x ,"\n") end ).()
|> ( fn lst -> lst -- [""] end ).()
end
def jpgFolderList(fp) do
Path.wildcard( Path.expand( fp ) <> "/**/*.jpg" )
|> Enum.map( &( Path.dirname( &1 )))
|> Enum.uniq
end
def mainImpl( foo ) do
" sortedFileNameList " |> IO.puts
Foo.sortedFileNameList(foo)
" resetAllTime " |> IO.puts
Foo.resetAllTime(foo)
" addOneSecond " |> IO.puts
Foo.addOneSecond(foo)
" myCheck " |> IO.puts
Foo.myCheck(foo) |> Enum.each( &( IO.puts( &1 )))
end
# 写真データーのExifデーターを変更できるようにするために権限を変える
def chmod644(fld) do
System.cmd("bash" , ["-c", "cd " <> fld <> " ; chmod 644 *jpg"] )
end
end
defmodule Main do
# 写真データーがあるフォルダを指定する
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
まえに書いたBashScript
より早くなってますね。パラレルが効いてるのでしょうか?
はまったところ
下記のようにTask.async_stream
を2重に使うと扱うデーター数が多くなるとタイムアウトでプログラムが止まってしまいます。今回の場合フォルダ数が5個以上の時にエラーが頻発しました
def addOneSecond( fp ) do
exifToolParam2
|> Task.async_stream( &( System.cmd("bash",["-c", &1]) ))
|> Enum.to_list()
end
Foo.jpgFolderList( baseFolder )
|> Task.async_stream( &( Foo.mainImpl( &1 ) ) ,[ timeout: :infinity, max_concurrency: 1000] )
|> Enum.to_list()
こんな感じのエラーがでます
(エラー回避)
内側の部分のアシンクを外します
def addOneSecond( fp ) do
exifToolParam2
|> Enum.each( &( System.cmd("bash",["-c" , &1]) ))
end
感想
ほむほむ
Elixir
いい感じ
冒頭のイラスト
ざっきー先生(山崎 進先生 @zacky1972さん )という、ヘイスガというGPU
でエリクサーの演算をするライブラリ?を開発されているすごい方です!この前もくもく会でお見かけした時はずっとチョコフレーク?をもぐもぐされてましたよ。