第16章 File类与Dir类

File.rename

①  更改文件名

②  将文件移动到其他现有目录下。若目录不存在,则会发生错误。此外,移动时无法跨越文件系统或磁盘驱动器。

File.rename(“before.txt”, “after.txt”)

File.rename(“data.txt”, “backup/data.txt”)

def copy(from, to)

  open(from) {|input|

open(to, “w”){|output|

  output.write(input.read)

}

}

end

文件复制需自定义,或者加上一行 “require fileutils“,就可以使用FileUtils.cp、FileUtil.mv等各种用来操作文件的方法。

FileUtil.mv方法可跨文件系统或磁盘驱动器移动文件。

require “fileutils”

FileUtils.cp(“data.txt”, “backup/data.txt”)

FileUtils,mv(“data.txt”, “backup/data1.txt”)

File.delete

File.unlink

删除文件

 

       

 

目录的操作

在Windows的命令提示符下,目录的分隔字符是“\”。但“\”代表转义字符,写在程序里很不方便,另外也无法在UNIX下运行,所以Ruby也支持在Windows下使用“/”作为分隔字符。

获取当前目录: Dir.pwd

 

更改当前目录: Dir.chdir

Dir.chdir方法的实参可以指定从当前目录算起的相对路径,也可以指定从 根目录算起的绝对路径。

p Dir.pwd   #=> “/usr/local/lib/ruby/1.8”

io.open(“find.rb”)

io.close

Dir.chdir(“../..”)   #=> 移动到两层之前的目录

p Dir.pwd        #=> 移动到两层之前的目录

io.open(“ruby/1.8/find.rb”)

io.close

Dir.chdir(“/etc”)     #=> 以绝对路径移动

p Dir.pwd          #=> “/etc”

读取目录操作

dir = Dir.open(“/usr/bin”)

while name = dir.read

  p name

end

dir.close

dir = Dir.open(“/usr/bi”){|dir|

  dir.each{|name|

    p name

}

}

Dir.open与File.open一样,使用语句块打开时,就可以省略调用close方法。这是,语句块内的参数是新建立的Dir对象。

执行Dir#read方法时,目录中的内容会依序逐个读出。这里可能读出的内容有下面4种:

l  代表当前目录的“.”

l  代表上层目录的“..”

l  其他下层目录名;

l  文件名

因此,“/usr/bin”与“usr/bin/.”所指的是同一个文件。

 

建立目录与删除目录

建立目录

Dir.mkdir(“temp”)

删除目录

Dir.rmdir(“temp”)

 

文件与目录的属性

使用File.stat方法,可以获取文件或目录的属性。File.stat方法的返回值会是File::Stat类的实例。

File::Stat类的实例方法

方法

返回值的意义

方法

返回值的意义

Dev

文件系统的装置代号

uid

文件所有者ID

Ino

i-node编号

gid

文件所有群组ID

mode

文件属性

redv

文件系统的装置类型

nlink

连接数量

size

文件大小

blksize

文件系统的区块大小

blocks

文件占用的区块数

atime

文件最后访问时间

mtime

文件最后修改时间

ctime

文件状态最后变更时间

 

 

其中,除了atime方法、mtime方法、ctime方法返回Time对象以外,其他方法返回的都是整数。

 

require ‘etc’

include Etc

st = File.stat(“/usr/local/bin/ruby”)

pw = getpwuid(st.uid)

p pw.name          #=> “root”

gr = getgrgid(st.gid)

p gr.name           #=> “wheel”

要从uid方法、gid方法所返回的整数中获取其对应的使用者名称与群组名称时,可以使用Etc模块。使用Etc模块时,应加上一行“require ‘etc’”。

 

mswin32版的Ruby不能使用Etc模块。

File.utime(atime, mtime, path)

修改文件path的最后访问时间atime与最后修改时间mtime。时间可以指定为整数值或Time对象。也可以同时指定不只一个路径名。

filename = “foo”

open(filename, “w”).close

st=File.stat(filename)

p st.ctime   #=> Sat Nov 11 19:10:22 +0800 2006

p st.mtime  #=> Sat Nov 11 19:14:05 +0800 2006

p st.atime   #=> Sat Nov 11 19:14:05 +0800 2006

 

File.utime(Time.now-100, Time.now-100, filename)

st = File.stat(filename)

p st.ctime   #=> Sat Nov 11 19:10:22 +0800 2006

p st.mtime  #=> Sat Nov 11 19:12:25 +0800 2006

p st.atime   #=> Sat Nov 11 19:12:25 +0800 2006

 

File.chmod(mode, path)

更改文件path的访问权限。mode应以整数值指定,同时可以指定不只一个文件路径。

* Windows文件的执行权限是由扩展名(.bat或.exe等)决定的,无法以这个方法更改。

 

访问权限是表示执行、写入、读取3种行为权限的3位整数值。而它又可以分别针对所有者、所有群组、其他人设定访问权限,所以总共以9个位表示。依次为:文件所有者的许可模式(读取、写入、执行)、文件所有群组的许可模式、其他人的许可模式。

因为八进制刚好以一个数字表示3个位,所以文件权限一般习惯使用八进制来写。

File.chmod(0755, “test.txt”)

将文件test.txt的许可权限设定成0755(文件所有者可做任何操作,其他人只能读取与执行)

rb_file = “rest.rb”

st = File.stat(rb_file)

File.chmod(st.mode | 0111, rb_file)  # 加上执行权限

只想要加上特定位时,则应使用File.stat方法获取现在的权限以后,加上指定位再设定回去。要加上位,应使用位和运算。

 

File.chown(owner, group, path)

更改文件path的所有者,同时可指定多个文件。执行这个方法时必须具有系统管理员权限。

 

FileTest模块

FileTest模块用来检查文件的属性。使用时可以读入使用,也可以当作模块函数来使用。

方法

返回值

exist?(path)

当path存在时返回true

file?(path)

当path是文件时返回true

directory?(path)

当path时目录时返回true

owned?(path)

当path的所有者与现在执行的使用者相同时返回true

grpowned?(path)

当path的所有群组与现在执行的使用者的群组相同时返回true

readable?(path)

当path可读时返回true

writable?(path)

当path可写时返回true

executable?(path)

当path可执行时返回true

size(path)

返回path的大小

size?(path)

当path大小小于0时返回true,为0时或文件不存在时返回false

zero?(path)

当path大小为0时返回true

 

文件名的操作

File.basename(path [, suffix])

从路径中获取文件名

返回path最后一个“/”后面的部分。指定了suffix(扩展名)时,返回值中的扩展名部分会被去掉。

p File.basename(“/usr/local/bin/ruby”)   #=> “ruby”

p File.basename(“src/ruby/file.c”, “.c”)    #=> “file”

 

File.dirname(path)

从路径中获取目录的部分

从path中获取前端到最后一个“/”为止的部分。当路径中没有“/”字符时,会返回“.”。

p File.dirname(“/ usr/local/bin/ruby”) 

#=> “/usr/local/bin”

p File.dirname(“ruby”)   #=> “.”

p File.dirname(“/”)      #=> “/”

File.extname(path)

从path中获取basename方法所取得的文件名部分中的扩展名部分。没有扩展名或文件名以“.”开始时,返回空字符串。

p File.extname(“helloruby.rb”)       #=> “.rb”

p File.extname(“ruby-1.8.5.tar.gz”)    #=> “.gz”

p File.extname(“/usr/local/bin/ruby”)  #=> “”

p File.extname(“~/.zshrc”)           #=> “”

File.split(path)

将path分解成目录名与文件名两部分,返回一个具有两个元素的数组。

p File.split(“/usr/local/bin/ruby”)

#=> [“/usr/local/bin”, “ruby”]

p File.split(“ruby”)       #=> [“.”, “ruby”]

p File.split(“/”)          #=> [“/”, “”]

File.join(dir, base)

File.split的反向操作

p File.join(“/usr/local/bin”, “ruby”)

#=> “/usr/local/bin/ruby”

p File.join(“.”, “ruby”)       #=> “./ruby”

File.expand_path(path [, default_dir])

p Dir.pwd         #=> “/usr/local”

p File.expand_path(“bin”)   #=> “/usr/local/bin”

p File.expand_path(“../bin”)  #=> “/usr/bin”

p File.expand_path(“bin”, “/usr”)  #=> “/usr/bin”

p File.expand_path(“../etc”, “/usr”) #=> “/etc”

 

在UNIX环境下,使用“~使用者名称”可以获取使用者的主目录。另外,”~/”则代表现在执行程序的使用者的主目录。

p File.expand_path(“~ /bin”)          #=> “/home/susan/bin”

p File.expand_path(“~helen/bin”)      #=> “/home/helen/bin”

 

与文件操作相关的程序库

  • find.rb

find.rb中所提供的Find模块,能够递归处理指定目录下所游子目录中的目录或文件。

Find.find(dir){|path|…}

将dir所指定的目录下所有路径传递给参数path进行处理

Find.prune

跳过现在正在查找的目录下的所有内容。单纯地使用next时,会跳过的只有这个目录,并不会跳过这个目录的子目录。

示例: 显示出实参top所指定的路径以下的所有目录。若在IGNORES录入了不想查找的目录时,则使用Find.prune方法跳过这些目录不查找。

require ‘find’

IGNORES = [/^\./, /^CVS$/, /^RCS$/]

def listdir(top)

  File.find(top) {|path|

if FileTest.directory?(path)    # 若path是目录

 dir, base = File.split(path)    # 多重赋值

 IGNORES.each{|re|

   if re =~ base            # 若是想要忽略的目录

     Find.prune           # 跳过这个目录不查找

   end

}

puts path                # 输出

end

}

end

listdir(ARGV[0])

 

  • tempfile.rb

tempfile.rb程序库用来管理暂存文件

tempfile.new(basename [,tempdir])

建立暂存文件。实际建立的文件名是basename加上进程ID与流水号的值。因此就算指定相同的basename,每次调用new方法产生出的文件也不会相同。没有指定tempdir时,会依序查找ENV[‘TEMPDIR’]、ENV[‘TMP’]、ENV[‘TEMP’]、’/tmp’,存放在最先找到的目录下。

tempfile.close(real)

关闭暂存文件。当real值为true时,暂存文件会即时删除。即使不要求删除,Tempfile对象也会在GC的时候自动删除。real的默认值是false。

tempfile.open

重新打开一度以close方法关闭的暂存文件

tempfile.path

返回暂存文件的路径

 

  • fileutils.rb

FileUtils.cp(from, to)

将文件从from复制到to。当to时目录时,则会在to下面建立与from同名的文件。from可以使用数组指定多个文件一次性复制,这时to一定要指定目录。

FileUtils.cp_r(from, to)

FileUtils.cp_rf(from, to)

与FileUtils.cp方法大致相同,差异在于当from是目录时,会反复地进行复制。FileUtils.cp_r方法在复制过程中发生错误时会停止执行,而FileUtils.cp_rf方法会忽略错误继续执行。

FileUtils.mv(from, to)

将文件从from移动到to。当to是目录时,则会移动到to下,文件名保留与from相同。from可以使用数组指定多个文件一次性移动,这时to一定要指定目录。

FileUtils.rm(path)

删除path。path必须是文件,可以数组方式指定多个。

FileUtils.rm_r(path)

FileUtils.rm_rf(path)

删除path。path如果是目录,则会反复地删除目录下的所有目录和文件。FileUtils.rm_r方法在复制过程中发生错误时会停止执行,而FileUtils.rm_rf方法会忽略错误继续执行。

FileUtils.compare(from, to [,option])

比较文件from与to的内容,相同时返回true,不同时返回false。

FileUtils.mkdir_p(path)

一次性建立多层目录

FileUtils.install(from, to [,option])

将文件从from复制到to。若to已经存在,内容也与from相同,则不做复制的动作。另外,选项option可以指定复制目标的文件访问权限。