天天看點

用R語言進行檔案系統管理

閱讀導讀:

1.R語言如何檢查檔案或目錄是否存在?如何重命名一個檔案?

2.R語言如何檢視和修改目錄的權限?

3.R語言如何删除一個檔案?

4.用R語言管理一個檔案系統時,都有哪些特殊的目錄?

5.如何檢視R軟體指定包所在目錄?

用R語言進行檔案系統管理

1. 檔案系統介紹

計算機的檔案系統是一種存儲群組織計算機資料的方法,它使得對其通路和查找變得容易,檔案系統使用檔案和樹形目錄的抽象邏輯概念代替了硬碟和CD光牒等實體裝置使用資料塊的概念,使用者使用檔案系統來儲存資料不必關心資料實際儲存在硬碟(或者CD光牒)的位址為多少的資料塊上,隻需要記住這個檔案的所屬目錄和檔案名。在寫入新資料之前,使用者不必關心硬碟上的那個塊位址沒有被使用,硬碟上的存儲空間管理(配置設定和釋放)功能由檔案系統自動完成,使用者隻需要記住資料被寫入到了哪個檔案中。

R語言和其他程式設計語言一樣,都有對檔案系統的操作,包括檔案操作和目錄操作,函數API都定義在base包中。

2. 目錄操作

系統環境:

  • Linux: Ubuntu Server 12.04.2 LTS 64bit
  • R: 3.0.1 x86_64-pc-linux-gnu

2.1 檢視目錄

檢視目前目錄下的子目錄。

# 啟動R程式

~ R

# 目前的目錄

> getwd()

[1] "/home/conan/R/fs"

# 檢視目前目錄的子目錄

> list.dirs()

[1] "."     "./tmp"

檢視目前目錄的子目錄和檔案。

> dir()

[1] "readme.txt" "tmp"

<span style="background-color: rgb(255, 255, 255);"># 檢視指定目錄的子目錄和檔案。</span>
<span style="background-color: rgb(255, 255, 255);"># 隻列出以字母R開頭的子目錄或檔案</span>

檢視目前目錄的子目錄和檔案,同dir()函數。

> list.files()

[1] "readme.txt" "tmp"

> list.files(".",all.files=TRUE)

[1] "."          ".."         "readme.txt" "tmp"

檢視完整的目錄資訊。

# 檢視目前目錄權限

> file.info(".")

  size isdir mode               mtime               ctime               atime  uid  gid uname grname

. 4096  TRUE  775 2013-11-14 08:40:46 2013-11-14 08:40:46 2013-11-14 08:41:57 1000 1000 conan  conan

# 檢視指定目錄權限

> file.info("./tmp")

      size isdir mode               mtime               ctime               atime  uid  gid uname grname

./tmp 4096  TRUE  775 2013-11-14 14:35:56 2013-11-14 14:35:56 2013-11-14 14:35:56 1000 1000 conan  conan

2.2 建立目錄

# 在目前目錄下,建立一個目錄

> dir.create("create")

> list.dirs()

[1] "."        "./create" "./tmp"

建立一個3級子目錄./a1/b2/c3

# 直接建立,出錯

> dir.create(path="a1/b2/c3")

Warning message:

In dir.create(path = "a1/b2/c3") :

  cannot create dir 'a1/b2/c3', reason 'No such file or directory'

# 遞歸建立,成功

> dir.create(path="a1/b2/c3",recursive = TRUE)

> list.dirs()

[1] "."          "./a1"       "./a1/b2"    "./a1/b2/c3" "./create"  "./tmp"

# 通過系統指令檢視目錄結構

> system("tree")

.

├── a1

│   └── b2

│       └── c3

├── create

├── readme.txt

└── tmp

2.3 檢查目錄是否存在

# 目錄存在

> file.exists(".")

[1] TRUE

> file.exists("./a1/b2")

[1] TRUE

# 目錄不存在

> file.exists("./aa")

[1] FALSE

2.4 檢查目錄的權限

檢查目錄的權限

> df<-dir(full.names = TRUE)

# 檢查檔案或目錄是否存在,mode=0

> file.access(df, 0) == 0

./a1     ./create ./readme.txt        ./tmp

TRUE         TRUE         TRUE         TRUE

# 檢查檔案或目錄是否可執行,mode=1,目錄為可以執行

> file.access(df, 1) == 0

./a1     ./create ./readme.txt        ./tmp

TRUE         TRUE        FALSE         TRUE

# 檢查檔案或目錄是否可寫,mode=2

> file.access(df, 2) == 0

./a1     ./create ./readme.txt        ./tmp

TRUE         TRUE         TRUE         TRUE

# 檢查檔案或目錄是否可讀,mode=4

> file.access(df, 4) == 0

./a1     ./create ./readme.txt        ./tmp

TRUE         TRUE         TRUE         TRUE

修改目錄權限。

# 修改目錄權限,所有使用者隻讀

> Sys.chmod("./create", mode = "0555", use_umask = TRUE)

# 檢視目錄完整資訊,mode=555

>  file.info("./create")

         size isdir mode               mtime               ctime               atime  uid  gid uname grname

./create 4096  TRUE  555 2013-11-14 08:36:28 2013-11-14 09:07:05 2013-11-14 08:36:39 1000 1000 conan  conan

# create目錄不可以寫

> file.access(df, 2) == 0

./a1     ./create ./readme.txt        ./tmp

TRUE        FALSE         TRUE         TRUE

2.5 對目錄重名

# 對tmp目錄重命名

> file.rename("tmp", "tmp2")

[1] TRUE

# 檢視目錄

> dir()

[1] "a1"         "create"     "readme.txt" "tmp2"

2.6 删除目錄

# 删除tmp2目錄

> unlink("tmp2", recursive = TRUE)

# 檢視目錄

> dir()

[1] "a1"         "create"     "readme.txt"

2.7 其他功能函數

拼接目錄字元串

# 拼接目錄字元串

> file.path("p1","p2","p3")

[1] "p1/p2/p3"

> dir(file.path("a1","b2"))

[1] "c3"

擷取最底層的子目錄名

# 目前目錄

> getwd()

[1] "/home/conan/R/fs"

# 最底層子目錄

> dirname("/home/conan/R/fs/readme.txt")

[1] "/home/conan/R/fs"

# 最底層子目錄或檔案名

> basename(getwd())

[1] "fs"

>  basename("/home/conan/R/fs/readme.txt")

[1] "readme.txt"

轉換檔案擴充路徑

# 轉換~為使用者目錄

> path.expand("~/foo")

[1] "/home/conan/foo"

标準化路徑,用來轉換win或linux的路徑分隔符

# linux

> normalizePath(c(R.home(), tempdir()))

[1] "/usr/lib/R"      "/tmp/RtmpqNyjPD"

# win

> normalizePath(c(R.home(), tempdir()))

[1] "C:\\Program Files\\R\\R-3.0.1"

[2] "C:\\Users\\Administrator\\AppData\\Local\\Temp\\RtmpMtSnci"

短路徑,縮減路徑的顯示長度,隻在win中運作。

# win

> shortPathName(c(R.home(), tempdir()))

[1] "C:\\PROGRA~1\\R\\R-30~1.1"

[2] "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\RTMPMT~1"

3. 檔案操作

3.1 檢視檔案

> dir()

[1]  "create"  "readme.txt"

# 檢查檔案是否存在

> file.exists("readme.txt")

[1] TRUE

# 檔案不存在

> file.exists("readme.txt222")

[1] FALSE

# 檢視檔案完整資訊

> file.info("readme.txt")

           size isdir mode               mtime               ctime               atime  uid  gid uname grname

readme.txt    7 FALSE  664 2013-11-14 08:24:50 2013-11-14 08:24:50 2013-11-14 08:24:50 1000 1000 conan  conan

# 檢視檔案通路權限,存在

>  file.access("readme.txt",0)

readme.txt

# 不可執行

>  file.access("readme.txt",1)

readme.txt

        -1

# 可寫

>  file.access("readme.txt",2)

readme.txt

# 可讀

>  file.access("readme.txt",4)

readme.txt

# 檢視一個不存在的檔案通路權限,不存在

> file.access("readme.txt222")

readme.txt222

           -1

判斷是檔案還是目錄。

# 判斷是否是目錄

> file_test("-d", "readme.txt")

[1] FALSE

> file_test("-d", "create")

[1] TRUE

# 判斷是否是檔案

> file_test("-f", "readme.txt")

[1] TRUE

> file_test("-f", "create")

[1] FALSE

3.2 建立檔案

# 建立一個空檔案 A.txt

> file.create("A.txt")

[1] TRUE

# 建立一個有内容的檔案 B.txt

> cat("file B\n", file = "B.txt")

> dir()

[1] "A.txt"      "B.txt"      "create"     "readme.txt"

# 列印A.txt

> readLines("A.txt")

character(0)

# 列印B.txt

> readLines("B.txt")

[1] "file B"

把檔案B.txt的内容,合并到 A.txt。

# 合并檔案

> file.append("A.txt", rep("B.txt", 10))

[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

# 檢視檔案内容

> readLines("A.txt")

[1] "file B" "file B" "file B" "file B" "file B" "file B" "file B" "file B" "file B" "file B"

把檔案A.txt複制到檔案C.txt

# 複制檔案

> file.copy("A.txt", "C.txt")

[1] TRUE

# 檢視檔案内容

> readLines("C.txt")

[1] "file B" "file B" "file B" "file B" "file B" "file B" "file B" "file B" "file B" "file B"

3.3 修改檔案權限

# 修改檔案權限,建立者可讀可寫可執行,其他人無權限

> Sys.chmod("A.txt", mode = "0700", use_umask = TRUE)

# 檢視檔案資訊

> file.info("A.txt")

      size isdir mode               mtime               ctime               atime  uid  gid uname grname

A.txt   70 FALSE  700 2013-11-14 12:55:18 2013-11-14 12:57:39 2013-11-14 12:55:26 1000 1000 conan  conan

3.4 檔案重命名

# 給檔案A.txt重命名為AA.txt

> file.rename("A.txt","AA.txt")

[1] TRUE

> dir()

[1] "AA.txt"     "B.txt"      "create"     "C.txt"      "readme.txt"

3.5 硬連接配接和軟連接配接

硬連接配接,指通過索引節點來進行連接配接。在Linux的檔案系統中,儲存在磁盤分區中的檔案不管是什麼類型都給它配置設定一個編号,稱為索引節點号(Inode Index)。在Linux中,多個檔案名指向同一索引節點是存在的。一般這種連接配接就是硬連接配接。硬連接配接的作用是允許一個檔案擁有多個有效路徑名,這樣使用者就可以建立硬連接配接到重要檔案,以防止“誤删”的功能。其原因如上所述,因為對應該目錄的索引節點有一個以上的連接配接。隻删除一個連接配接并不影響索引節點本身和其它的連接配接,隻有當最後一個連接配接被删除後,檔案的資料塊及目錄的連接配接才會被釋放。也就是說,檔案真正删除的條件是與之相關的所有硬連接配接檔案均被删除。

軟連接配接,也叫符号連接配接(Symbolic Link)。軟連結檔案有類似于Windows的快捷方式。它實際上是一個特殊的檔案。在符号連接配接中,檔案實際上是一個文本檔案,其中包含的有另一檔案的位置資訊。

硬連接配接和軟連接配接,隻在Linux系統中使用。

# 硬連接配接

> file.link("readme.txt", "hard_link.txt")

[1] TRUE

# 軟連接配接

> file.symlink("readme.txt", "soft_link.txt")

[1] TRUE

# 檢視檔案目錄

> system("ls -l")

-rwx------ 1 conan conan   70 Nov 14 12:55 AA.txt

-rw-rw-r-- 1 conan conan    7 Nov 14 12:51 B.txt

dr-xr-xr-x 2 conan conan 4096 Nov 14 08:36 create

-rw-rw-r-- 1 conan conan   70 Nov 14 12:56 C.txt

-rw-rw-r-- 2 conan conan    7 Nov 14 08:24 hard_link.txt

-rw-rw-r-- 2 conan conan    7 Nov 14 08:24 readme.txt

lrwxrwxrwx 1 conan conan   10 Nov 14 13:11 soft_link.txt -> readme.txt

檔案hard_link.txt是檔案readme.txt硬連接配接檔案,檔案soft_link.txt是檔案readme.txt軟連接配接檔案,

3.5 删除檔案

有兩個函數可以使用file.remove和unlink,其中unlink函數使用同删除目錄操作是一樣的。

# 删除檔案

> file.remove("A.txt", "B.txt", "C.txt")

[1] FALSE  TRUE  TRUE

# 删除檔案

> unlink("readme.txt")

# 檢視目錄檔案

> system("ls -l")

total 12

-rwx------ 1 conan conan   70 Nov 14 12:55 AA.txt

dr-xr-xr-x 2 conan conan 4096 Nov 14 08:36 create

-rw-rw-r-- 1 conan conan    7 Nov 14 08:24 hard_link.txt

lrwxrwxrwx 1 conan conan   10 Nov 14 13:11 soft_link.txt -> readme.txt

# 列印硬連接配接檔案

> readLines("hard_link.txt")

[1] "file A"

# 列印軟連接配接檔案,soft_link.txt,由于原檔案被删除,有錯誤

> readLines("soft_link.txt")

Error in file(con, "r") : cannot open the connection

In addition: Warning message:

In file(con, "r") :

  cannot open file 'soft_link.txt': No such file or directory

4. 幾個特殊的目錄

R.home() 檢視R軟體的相關目錄

.Library 檢視R核心包的目錄

.Library.site 檢視R核心包的目錄和root使用者安裝包目錄

.libPaths() 檢視R所有包的存放目錄

system.file() 檢視指定包所在的目錄

4.1 R.home() 檢視R軟體的相關目錄

# 列印R軟體安裝目錄

> R.home()

[1] "/usr/lib/R"

# 列印R軟體bin的目錄

> R.home(component="bin")

[1] "/usr/lib/R/bin"

# 列印R軟體檔案的目錄

>  R.home(component="doc")

[1] "/usr/share/R/doc"

通過系統指令,找到R檔案的位置。

# 檢查系統中R檔案的位置

~ whereis R

R: /usr/bin/R /etc/R /usr/lib/R /usr/bin/X11/R /usr/local/lib/R /usr/share/R /usr/share/man/man1/R.1.gz

# 列印環境變量R_HOME

~ echo $R_HOME

/usr/lib/R

通過R.home()函數,我們可以很容易的定位R軟體的目錄。

4.2 R軟體的包目錄

# 列印核心包的目錄

> .Library

[1] "/usr/lib/R/library"

# 列印核心包的目錄和root使用者安裝包目錄

> .Library.site

[1] "/usr/local/lib/R/site-library" "/usr/lib/R/site-library"

[3] "/usr/lib/R/library"

# 列印所有包的存放目錄

> .libPaths()

[1] "/home/conan/R/x86_64-pc-linux-gnu-library/3.0"

[2] "/usr/local/lib/R/site-library"

[3] "/usr/lib/R/site-library"

[4] "/usr/lib/R/library"

4.3 檢視指定包所在的目錄

# base包的存放目錄

> system.file()

[1] "/usr/lib/R/library/base"

# pryr包的存放目錄

>  system.file(package = "pryr")

[1] "/home/conan/R/x86_64-pc-linux-gnu-library/3.0/pryr"

其實,用R語言操作檔案系統還是很友善的。但對于函數命名确實不太規範,需要我們花時間記憶。

繼續閱讀