BlankTar

about | blog | works | photo

昨日のディレクトリ操作に引き続いて、本日はElixirでファイル入出力をやってみます。

簡単な読み書き

単純に読み込む/書き込むだけならものすごく簡単で、以下のように出来ます。

iex> File.write "test.txt", "hello"
:ok
iex> File.read "test.txt"
{:ok, "hello"}

iex> File.write "test.txt", " world", [:append]
:ok
iex> File.read "test.txt"
{:ok, "hello world"}

一回目の書き込みが通常の上書き的な書き込み、二回目の書き込みが追記書き込みになっています。
File.writeの第三引数にオプションを渡すわけですね。使えるオプションについては後述。

ファイルハンドラを使った読み書き

一般的なopenしてwriteして…って流れでも読み書きが出来ます。以下のような感じ。

iex> File.write "test.txt", "はろーわーるど"
:ok

iex> {:ok, fp} = File.open "test.txt"
{:ok, #PID<0.100.0>}

iex> IO.binread fp, 3
"は"

iex> File.close fp
:ok

デフォルトでは読み込みモード、バイナリモード?で開かれるようです。
IO.binreadの第二引数はバイト数です。3文字読みたかったのに1文字しか返って来ませんでした。

ファイルがutf-8で保存されているなら、utf-8モードが使えます。

iex> {:ok, fp} = File.open "test.txt", [:utf8]
{:ok, #PID<0.100.0>}

iex> IO.read fp, 3
"はろー"
iex> IO.read fp, 4
"わーるど"
iex> IO.read fp, 1
:eof

iex> File.close fp
:ok

IO.binreadではなくてIO.readになりました。ちゃんと文字数で指定出来ています。
ファイルの終了まで行ったら:eofが返るのもポイントですね。

書き込みも何の捻りもなく以下のように行ないます。

iex> {:ok, fp} = File.open "test.txt", [:write, utf8]
{:ok, #PID<0.100.0>}

iex> IO.binwrite fp, "はろー"
:ok

iex> File.close fp
:ok

iex> File.read "test.txt"
{:ok, "はろー"}

openするときにオプションに:writeを渡すだけです。

オプション

:read:writeはそのまんま読み込みモード/書き込みモードです。
両方指定すると読み書き両方出来るようになります。
:readを指定しているときは存在しないとエラーに、:writeを指定しているときは存在しなければ作るようです。

:appendを指定すると追記書き込みになります。上でちょこっと使ったやつです。
存在しない場合は新規作成になります。

:exclusiveオプションを:writeと同時に使うと、ファイルが存在するとエラーが返るようになります。
新規作成だけを認める場合に使うオプションですね。

:char_list:utf8を使うと読み込んだときに返る型を決められるようです。
何も付けないとbinaryで返るようになっています。
エンコーディングについては:utf16utf32:big:littleなど、色々オプションがあるようです。

:compressedを付けるとファイルがgzipで圧縮されるようになります。
圧縮レベルなどのオプションもあるのかもしれませんが、見付けられませんでした。

:delayed_write:syncを付けると、書き込みを即座に行なうかバッファするかを選べます。
デフォルトでは:syncのようです。細かく沢山書き込むときは:delayed_writeにしておくのが賢いのかも?

参考:
File - Elixir v1.2.5
IO - Elixir v1.2.5

何を思ったのか、Elixirなる言語を触り始めました。
なんだかよく分かりませんが、なんだかとっても楽しい言語です。
ただ、新しい言語だけあってやたらとドキュメントが無いのがかなしい。

で、この記事はElixirを使ったディレクトリの操作についてのまとめです。

p.s. 2016-06-19

ファイルの読み書きについての記事も書きました。併せてどうぞ。

ファイルの存在確認

あるファイルが存在するかどうか確認するにはFile.exists?関数を使います。

iex> File.exists? "/"
true

ディレクトリかどうか調べる

ファイルなのかディレクトリなのかを見分けるにはFile.dir?関数を使います。

iex> File.dir? "/dev"
true
iex> File.dir? "/dev/null"
false

ディレクトリの中身を見る

File.ls関数でファイル/ディレクトリの一覧を取得出来ます。

iex> File.ls
{:ok, ["files", "of", "current", "directory"]}
iex> File.ls "/path/to/directory"
{:ok, ["hoge.txt", "fuga.mp3", "foo.png"]}

引数省略でカレントディレクトリの情報を取得出来るとか、まんまシェルのlsコマンドって感じ。

カレントディレクトリを変える

ls関数があればcd関数もあります。

iex> File.cd "/path/to/dir"
:ok

lsでは引数省略が出来ますが、こっちは引数省略は出来ないようです。

cwd関数でカレントディレクトリを取得出来ます。

iex> File.cwd
{:ok, "/mnt"}

ディレクトリを作ったり消したり

ディレクトリの作成はmkdir関数で。
mkdir_p関数を使うと親ディレクトリも込みで作ってくれます。

iex> File.ls
{:ok, []}
iex> File.mkdir "dir"
:ok
iex> File.mkdir_p "path/to/dir"
:ok
File.ls
{:ok, ["dir", "path"]}

普通にシェルって感じです。

ディレクトリの削除にはrmdir関数を使います。
rmdir関数は空のディレクトリしか消せませんが、rm_rf関数を使えば中身があっても消せます。もう完全にシェルって感じです。

iex> File.mkdir_p "hoge/fuga/foo"
:ok
iex> File.rmdir "hoge/fuga"
{:error, :eexist}
iex> File.rm_rf "hoge/fuga"
{:ok, ["hoge/fuga", "hoge/fuga/foo"]}
iex> File.rmdir "hoge"
:ok

エラーチェックを省略する

ここまでの例では、戻り値の最初の値は全て:okや:errorになっていました。
Elixirではこの値を使ってエラーチェックをするのが通常らしいです。

エラーチェックが面倒臭かったら、関数名の後に感嘆符を付けると良いようです。
感嘆符を付けた関数を使うと、戻り値で失敗を伝える代わりに例外を投げてくれるようになります。

こんな感じ。

iex> File.ls "not-found-directory"
{:error, :enoent}
iex> File.ls! "not-found-directory"
** (File.Error) could not list directory not-found-directory: no such file or directory
	(elixir) lib/file.ex:1167: File.ls!/1

ls以外の関数でもFileモジュールの中の関数ではだいたい使えるっぽいです。

参考: File - Elixir v1.2.5

dockerというコンテナ型の仮想化ソフトがありますよね。
セキュリティが宜しくないとかで、置き換えを目指すrktという別のソフトウェアが出て来ていたりします。

調べてみたところ、dockerグループに属した一般ユーザーがrootの権限を使えるらしいです。ヤバそうです。試してみました。

ひとまず、ubuntuか何かのイメージを落してきます。使うイメージはなんでも良いと思います。
ちなみにホストマシンにはCoreOSを使ってみました。

ホストマシン $ docker pull ubuntu

出来たら、起動します。

ホストマシン $ docker run -itv /:/mnt ubuntu /bin/bash

ホストマシンのルートディレクトリを/mntにマウントしている、というのがポイントです。
あとのオプションは適当に調べてください。

次に、ホストマシンのルートディレクトリにchrootを行ないます。

コンテナ # chroot /mnt /bin/bash

これでホストマシンのrootに(擬似的に)なれました。

rootのパスワードを変えます。

chrootしたあと # passwd

これが出来たら、あとはexit2回でマシンを閉じます。

設定したパスワードでログイン出来るか試してみましょう。

ホストマシン $ su -
Password:

普通にrootになれると思います。

ね、簡単でしょう?
共有サーバーで運用する場合、dockerグループも迂闊に渡さないようにしたほうが良さそうです…。

[ << ] [ 3 ] [ 5 ] [ 7 ] [ >> ]