Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

みなさん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というファイル名を取得してみます。

program.pl
use Path::Tiny;

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

print $txt->basename;

実行結果
CBR250RR.txt

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

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

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

use Path::Tiny;

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

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

実行結果
CBR250RR

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

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

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

絶対パスの取得 (absolute)

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

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

相対パスの取得 (relative)

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

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

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

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

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

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

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

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

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

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

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

ファイル操作

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

ファイルのコピー (copy)

copy(コピー先)

program.pl
use Path::Tiny;

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

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

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

CB400SF.txtが増えましたね!

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

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

move(移動先)

program.pl
use Path::Tiny;

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

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

CBR250RR.txthondaフォルダの中に入りましたね!

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

program.pl
use Path::Tiny;

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

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

CBR250RR.txtCBR250R.txtに変わりました!

ファイルの削除 (remove)

program.pl
use Path::Tiny;

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

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

CBR250RR.txtが消えたッ!

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

program.pl
use Path::Tiny;

my $dir = path("honda");

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

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

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

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

program.pl
use Path::Tiny;

my $dir = path("honda");

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

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

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

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

program.pl
use Path::Tiny;

my $dir = path("kawasaki");

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

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

他のファイルを扱う

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

program.pl
use Path::Tiny;

my $dir = path("honda");

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

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

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

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

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

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

program.pl
use Path::Tiny;

my $dir = path("honda");

foreach my $file ($dir->children(qr/^(NC|Rebel)/)) {
    printf "%s\n", $file->basename;
}
実行結果
NC750X.txt
Rebel250.txt

うん 便利ぃ~

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

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

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

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

なんじゃこりゃー!

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

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

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

program.pl
use Path::Tiny;

my $dir = path("honda");

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

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

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

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

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;
}

実行結果
CBR250RR.txt is exists.
CBR1000RR.txt is not exists.

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

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

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;
}
実行結果
CBR250RR.txt is file.
honda is dir.

判定できました!

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

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

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

program.pl
use Path::Tiny;

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

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

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

program.pl
use Path::Tiny;

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

my $dir = $txt->parent;

print $dir;
実行結果
honda

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

まとめ

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

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

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

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

hiro_nico
見習いエンジニア Go / Perl など勉強中
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした