Path::Tinyでファイルを扱おう

# はじめに

みなさんPerl書いてますかー！

今回も引き続き、`Path::Tiny`というモジュールを紹介します。

このモジュールを使うことで・・・

* テキストファイルの読み書きが簡単に！
* ファイルの扱いが簡単に！

いろいろできるので試しつつ順に紹介していきます。

前回は、「テキストファイルの読み書きが簡単に！」の部分をご紹介しました。
https://qiita.com/hiro_nico/items/204b4fa4500edcc07268

基本的な使い方は、前回書いたので省略します。

今回は、
「ファイルの扱いが簡単に！」の部分をお送りします。

# Path::Tiny

http://search.cpan.org/perldoc?Path%3A%3ATiny

## ファイルパス

ファイルを扱う処理をするときは、ファイルパスについても処理しますよね。
Path::Tiny使えばいろんなことが簡単にできますよ！

例えば
下記のようなファイル構成で話をしていきます。

```
C:\tmp>tree /f
C:.
│  CBR250RR.txt
│  program.pl
│
└─honda
        GOLDWING.txt
        NC750X.txt
        Rebel250.txt
```

### ファイル名の取得 (basename)

まず`CBR250RR.txt`というファイル名を取得してみます。

```perl:program.pl
use Path::Tiny;

my $txt = path("CBR250RR.txt");

print $txt->basename;

```
```text:実行結果
CBR250RR.txt
```

これくらいなら書かなくてもよいくらいですね・・・ｗ

Path::Tinyオブジェクトに対して使うと
ファイル名の取得できます。

`CBR250RR.txt`から拡張子を抜いた部分を取得することもできます。

```perl
use Path::Tiny;

my $txt = path("CBR250RR.txt");

print $txt->basename('.txt');

```
```text:実行結果
CBR250RR
```

また下記のように指定することもできるようです。

```perl:
# 正規表現で拡張子を指定する
$txt->basename(qr/\.txt/);

# 配列から拡張子を指定する
my @suffixes = ('.txt', '.pl');
$txt->basename(@suffixes);
```

### 絶対パスの取得 (absolute)

```perl:program.pl
use Path::Tiny;
my $txt = path("CBR250RR.txt");

print $txt->absolute;
```
```text:実行結果
C:/tmp/CBR250RR.txt
```

### 相対パスの取得 (relative)

`relative("基準とするところ")`

```perl:program.pl
use Path::Tiny;
my $txt = path("CBR250RR.txt");

print $txt->relative("honda");
```
```text:実行結果
../CBR250RR.txt
```

`CBR250RR.txt`は、`honda`フォルダの一個上ってことで合ってますね。

### 実行環境に合わせてファイルパスを表示 (canonpath)

Windows環境で実行していますが
先程までのファイルパス表示を見てみると
スラッシュ区切り(`/`)となってしまっています。

`canonpath`を使用すると、windowsなら`\`区切りで表示してくれます。

```perl:program.pl
use Path::Tiny;
my $txt = path("CBR250RR.txt");

print $txt->absolute . "\n";

print $txt->absolute->canonpath;
```
```text:実行結果
C:/tmp/CBR250RR.txt
C:\tmp\CBR250RR.txt
```

これならファイルパスを使うときに
`ファイルが見つからんぞゴラァ！`
と怒られることはなさそうですねｗ

## ファイル操作

コピーや移動や削除もできちゃいますよ！

### ファイルのコピー (copy)

`copy(コピー先)`

```perl:program.pl
use Path::Tiny;

my $txt = path("CBR250RR.txt");

$txt->copy("CB400SF.txt");

```
```text:実行後
C:.
│  CB400SF.txt
│  CBR250RR.txt
│  program.pl
│
└─honda
        GOLDWING.txt
        NC750X.txt
        Rebel250.txt
```

`CB400SF.txt`が増えましたね！

### ファイルの移動・リネーム (move)

ファイルの移動とリネームには、`move`を使います。

`move(移動先)`

```perl:program.pl
use Path::Tiny;

my $txt = path("CBR250RR.txt");

$txt->move('C:\tmp\honda\CBR250RR.txt');
```
```text:実行後
C:.
│  program.pl
│
└─honda
        CBR250RR.txt
        GOLDWING.txt
        NC750X.txt
        Rebel250.txt
```

`CBR250RR.txt`が`honda`フォルダの中に入りましたね！

リネームする場合も同じように・・・

```perl:program.pl
use Path::Tiny;

my $txt = path("CBR250RR.txt");

$txt->move('CBR250R.txt');
```
```text:実行後
C:.
│  CBR250R.txt
│  program.pl
│
└─honda
        GOLDWING.txt
        NC750X.txt
        Rebel250.txt
```

`CBR250RR.txt`が`CBR250R.txt`に変わりました！

### ファイルの削除 (remove)

```perl:program.pl
use Path::Tiny;

my $txt = path("CBR250RR.txt");

$txt->remove;
```
```text:実行後
C:.
│  program.pl
│
└─honda
        GOLDWING.txt
        NC750X.txt
        Rebel250.txt
```

`CBR250RR.txt`が消えたッ！

ちなみにフォルダは消せません・・・

```perl:program.pl
use Path::Tiny;

my $dir = path("honda");

$dir->remove;
```
```text:実行結果
C:\tmp>perl program.pl
Error unlink on 'honda': Is a directory at program.pl line 5.
```

`ディレクトリだから消せねえよ！！`って怒られました(´・ω・｀)

### ディレクトリの削除 (remove_tree)

これを使えば消せますよ！

```perl:program.pl
use Path::Tiny;

my $dir = path("honda");

$dir->remove_tree;
```
```text:実行後
C:.
    CBR250RR.txt
    program.pl

サブフォルダーは存在しません
```

### ディレクトリの作成 (mkpath)

消したら作りたいじゃないですか？(いつもの

```perl:program.pl
use Path::Tiny;

my $dir = path("kawasaki");

$dir->mkpath;
```
```text:実行後
C:.
│  CBR250RR.txt
│  program.pl
│
├─honda
│      GOLDWING.txt
│      NC750X.txt
│      Rebel250.txt
│
└─kawasaki
```

`kawasaki`フォルダが増えました。ヤッター！

## 他のファイルを扱う

### フォルダ内のファイルを取得 (children)

```perl:program.pl
use Path::Tiny;

my $dir = path("honda");

foreach my $file ($dir->children) {
    printf "%s\n", $file->basename;
}
```
```text:実行結果
GOLDWING.txt
NC750X.txt
Rebel250.txt
```

フォルダ内にあるファイル一覧が表示できました。

`children`から返ってくるものは、
Path::Tinyオブジェクトになっているので
紹介してきたような関数がそのまま呼べちゃいます！

あとは、フォルダ内の特定の拡張子だけとか取りたくなるじゃないですか？

そういった場合も、
`children(qr/\.pl/)`など正規表現で取得するものを絞ることもできます。

拡張子だけでなくファイル名で絞ることもできますよ！

```perl:program.pl
use Path::Tiny;

my $dir = path("honda");

foreach my $file ($dir->children(qr/^(NC|Rebel)/)) {
    printf "%s\n", $file->basename;
}
```

```text:実行結果
NC750X.txt
Rebel250.txt
```

うん 便利ぃ～

`children`はフォルダ内のファイルだけではなく
フォルダ内にフォルダがあった場合も同じく取得してくれます。

ファイルかフォルダかの判定は後述・・・

### 指定したファイルを取得 (child)

`children`と似たような名前で`child`という関数があります。

なんじゃこりゃー！

って思った人もいるのではないでしょうか？(私は思いました)

`child`は、指定したファイルやディレクトリのPath::Tinyオブジェクトを取得できます。
基本的にはフォルダ(Path::Tinyオブジェクト)に対して使う感じですかね。

使い方は、以下のような感じ。

```perl:program.pl
use Path::Tiny;

my $dir = path("honda");

my $txt = $dir->child("Rebel250.txt");

print $txt->absolute;
```
```text:実行結果
C:/tmp/honda/Rebel250.txt
```

### ファイルの存在有無 (exists)

存在する`CBR250RR.txt`と存在しない`CBR1000RR.txt`で確認してみます。

```perl:program
use Path::Tiny;

my $txt1 = path("CBR250RR.txt");
my $txt2 = path("CBR1000RR.txt");

if ($txt1->exists) {
    printf "%s is exists.\n", $txt1;
} else {
    printf "%s is not exists.\n", $txt1;
}

if ($txt2->exists) {
    printf "%s is exists.\n", $txt2;
} else {
    printf "%s is not exists.\n", $txt2;
}

```
```text:実行結果
CBR250RR.txt is exists.
CBR1000RR.txt is not exists.
```

ちゃんと判定できましたね。

### ファイル・ディレクトリの判定 (is_file, is_dir)

```perl:
use Path::Tiny;

my $txt = path("CBR250RR.txt");

my $dir = path("honda");

if ($txt->is_file) {
    printf "%s is file.\n", $txt;
}

if ($dir->is_dir) {
    printf "%s is dir.\n", $dir;
}
```
```text:実行結果
CBR250RR.txt is file.
honda is dir.
```

判定できました！

私は`children`のときとかによく使ったりしますネ～

### 親ディレクトリを取得する (parent)

`path(ファイルパス)`と書いてましたが、
実は`path(フォルダ, ファイル名)`というように
複数指定するとファイルパスをつなげてくれるんですよー！

```perl:program.pl
use Path::Tiny;

my $txt = path("honda", "GOLDWING.txt");

print $txt;
```
```text:実行結果
honda/GOLDWING.txt
```

話がそれましたが・・・ｗ
親ディレクトリを取得するときは、`parent`を使用します。

```perl:program.pl
use Path::Tiny;

my $txt = path("honda", "GOLDWING.txt");

my $dir = $txt->parent;

print $dir;
```
```text:実行結果
honda
```

深くもぐるには`child`を使ってファイルなどを取得して、
上に戻るときには`parent`を使えば
親ディレクトリのPath::Tinyオブジェクトを取得できるというわけですね！

# まとめ

ここまで`Path::Tiny`を使った便利な関数を紹介してきました。

まだこれでも半分くらいでしょうか・・・？

まだまだできることがあるので、
深く知りたい場合は、Path::Tinyの公式ドキュメントを見てみてくださいね！

(やる気があれば、もう1記事くらい書くかも？)