ファイルのパスの情報を扱うならfsパッケージを使うと便利。
さて、fs
パッケージのお話です。前回から結構あいてしまいました。
fs
パッケージでファイルのpathについて扱う関数はpath_***
という名前になっています。
path
で始まる関数は下記のようです。
ls(envir = asNamespace("fs"), pattern = "^path_*") #> [1] "path" "path_" "path_abs" #> [4] "path_common" "path_dir" "path_expand" #> [7] "path_expand_r" "path_ext" "path_ext_remove" #> [10] "path_ext_set" "path_ext<-" "path_file" #> [13] "path_filter" "path_home" "path_home_r" #> [16] "path_join" "path_norm" "path_package" #> [19] "path_real" "path_rel" "path_sanitize" #> [22] "path_split" "path_temp" "path_tidy"
ここから、exportされている関数について順に見ていきます。
ファイルパスについては原則としてそのファイルパスに実際にディレクトリやファイルが存在してもしなくてもエラーになりません。
また、区切り文字は"/"で、Windowsの"\"の形で与えても動作し、出力は全て"/"に変更されます(書式が環境に依存しない点がfs
パッケージの良いところの1つです)
path()
関数は任意の数の引数を...
として受け取りますが、他は原則としてc()
でまとめて与えてあげないといけません。
その代わり、まとめさえすればいくつ与えても同じ処理をしてくれますので、変数にまとめてから与えれば一度に処理されるためコードも見やすく実行速度も良いというコードの出来あがりですね。
path()
与えられた引数からファイルパスを構成して返してくれます。here
パッケージのhere()
と同様の動きですね(fs::path
は拡張子も与えられるが)
## プロジェクトのroot(今回はC:/Users/niszet/Documents/r work/test4blog/)を起点としたファイルパスを返す) here::here("hoge", "fuga") #> [1] "C:/Users/niszet/Documents/r work/test4blog/hoge/fuga"
Helpにある実行例をコピペ。here
と違って、プロジェクトのrootを起点としたパスになりませんが、そのための関数は別途あります。この結果をhere()
に与えても良いですね。
fs::path("foo", "bar", "baz", ext = "zip") #> foo/bar/baz.zip
このようにすっきりと書けます。
わざわざstringr
パッケージを使って書かなくても良いわけです。便利ですね。
stringr::str_c(c(stringr::str_c(c("foo", "bar", "baz"), collapse = "/"), "zip"), collapse = ".") #> [1] "foo/bar/baz.zip"
path_abs()
こちらは絶対パスで返してくれる関数。起点は引数start
に与え、デフォルトは現在いるディレクトリ.
になっています(下記では明示的に与えていますが。現在いるディレクトリはプロジェクトのルートにしています)
fs:::path_abs(path = "a", start = ".") #> [1] C:/Users/niszet/Documents/r work/test4blog/a
あまり意味はないですが、プロジェクトルートを起点として明示すればこのようになります。(これはhere()
に直接渡した方が良いが)
fs:::path_abs(path = "a", start = here::here()) #> [1] C:/Users/niszet/Documents/r work/test4blog/a
相対パス <-> 絶対パス変換は地味に使うので、こういうのがあると便利ですね。絶対パス->相対パスはpath_rel()
を参照してください。
path_common()
任意の数のpathを表す文字列を受け取り、その共通部分を返します。例えば下記の例であれば、"aaa/bbb"までが共通ですのでこの文字列が返ってきます。
path("aaa", "bbb" , "ccc") #> aaa/bbb/ccc path("aaa", "bbb" , "ddd") #> aaa/bbb/ddd path_common(c(path("aaa", "bbb" , "ccc"), path("aaa", "bbb" , "ddd"))) #> aaa/bbb
path_dir()
パスのディレクトリ部分を返す関数。実際には最後の"/"からうしろを削除する動きをしているようなので、そのパスがディレクトリを示している可能性がある場合はあらかじめis_dir()
を使ってそのパスは弾いておきましょう
path_dir(c("aaa/bbb/ccc","aaa/bbb/ddd")) aaa/bbb aaa/bbb
path_expand(), path_expand_r()
~
を展開してくれます。
path_expand("~") #> C:/Users/niszet path_expand_r("~") #> C:/Users/niszet/Documents
path_expand()
のWindows上の挙動はpath.expand()
とは異なるようです。path_expand_r()
はその挙動を再現した動きをするようです。
詳細についてはHelpを参照してください。
path.expand("~") #> [1] "C:/Users/niszet/Documents"
path_ext()
拡張子を取り出す関数。
path_ext("aaa/bbb.txt") #> [1] "txt"
path_ext_remove()
拡張子だけを削除する関数。
path_ext_remove("aaa/bbb.txt") aaa/bbb
これらの関数は、右から見てはじめて出てきた"."から右を拡張子、左を残りとしているので、
path_ext_remove("aaa.bbb/ccc/ddd") #> aaa path_ext("aaa.bbb/ccc/ddd") #> [1] "bbb/ccc/ddd"
といった挙動になります。気をつけましょう。
path_ext_set()
拡張子を与えます。既にある場合は置き換えます。
path_ext_set("aaa/bbb", "txt") #> aaa/bbb.txt path_ext_set("aaa/bbb.zip", "txt") #> aaa/bbb.txt
これも先の例と同様の拡張子の判断なので注意。
path_file()
ファイル部分を返す。
path_file("aaa/bbb.txt") #> bbb.txt
これも最後の"/"から右を返す、という挙動なので拡張子がない場合は下記のようになる。
path_file("aaa/bbb") #> bbb
path_filter()
ファイルパスに対して、正規表現を使って絞り込むことが出来る。regexp
だけじゃなくglob
でもよい。
## 英字1文字にマッチし、そのあとにその文字が1文字以上続く、というパタン(要するにaa, aaa, aaaa, ..., bb, bbb, ... のようなパタンがあればマッチ) path_filter(c("aaa/bbb", "abc/def"), regexp = "(\\w)\\1+") #> aaa/bbb
また、invert = TRUE
にするとマッチしないものが返ってくる。
path_filter(c("aaa/bbb", "abc/def"), regexp = "(\\w)\\1+", invert = TRUE) #> abc/def
これも地味に便利(正規表現を書き間違えてハマるまでが様式美)
量が多くなってきたので、ここで一旦切ります。
path_
周りはようやく半分、です。折り返し。
fs
パッケージ、ファイルの操作・処理を行うときなどには必須になります。是非使いこなしましょう!1
Enjoy!!
-
私がね…↩