Процесс всегда работает от имени какого-то пользователя (возможно, root
), поэтому с ним связан File::Stat
есть методы экземпляра для получения такой информации.
info = File.stat('/tmp/secrets')
rflag = info.readable?
wflag = info.writable?
xflag = info.executable?
Иногда нужно отличить действующий идентификатор пользователя от реального. На этот случай предлагаются методы экземпляра readable_real?
, writable_real?
и executable_real?
.
info = File.stat('/tmp/secrets')
rflag2 = info.readable_real?
wflag2 = info.writable_real?
xflag2 = info.executable_real?
Можно сравнить владельца файла с действующим идентификатором пользователя (и идентификатором группы) текущего процесса. В классе File::Stat
для этого есть методы owned?
и grpowned?
.
Отметим, что многие из этих методов можно найти также в модуле FileTest
:
rflag = FileTest::readable?('pentagon_files')
# Прочие методы: writable? executable? readable_real?
# writable_real? executable_real? owned? grpowned?
# Отсутствуют здесь: uid gid mode.
Маска umask
, ассоциированная с процессом, определяет начальные разрешения для всех созданных им файлов. Стандартные разрешения 0777
логически пересекаются (AND) с отрицанием umask
, то есть биты, поднятые в маске, «маскируются» или сбрасываются. Если вам удобнее, можете представлять себе эту операцию как вычитание (без занимания). Следовательно, если задана маска 022
, то все файлы создаются с разрешениями 0755
.
Получить или установить маску можно с помощью метода umask
класса File
. Если ему передан параметр, то он становится новым значением маски (при этом метод возвращает старое значение).
File.umask(0237) # Установить umask.
current_umask = File.umask # 0237
Некоторые биты режима файла (например, бит фиксации — sticky bit) не имеют прямого отношения к разрешениям. Эта тема обсуждается в разделе 10.1.12.
10.1.10. Получение и установка временных штампов
С каждым файлом на диске связано несколько
Получить эту информацию можно тремя разными способами, хотя все они дают один и тот же результат.
Методы mtime
, atime
и ctime
класса File
возвращают временные штампы, не требуя предварительного открытия файла или даже создания объекта File
.
t1 = File.mtime('somefile')
# Thu Jan 04 09:03:10 GMT-6:00 2001
t2 = File.atime('somefile')
# Tue Jan 09 10:03:34 GMT-6:00 2001
t3 = File.ctime('somefile')
# Sun Nov 26 23:48:32 GMT-6:00 2000
Если файл, представленный экземпляром File
, уже открыт, то можно воспользоваться методами этого экземпляра.
myfile = File.new('somefile')
t1 = myfile.mtime
t2 = myfile.atime
t3 = myfile.ctime
А если имеется экземпляр класса File::Stat
, то и у него есть методы, позволяющие получить ту же информацию:
myfile = File.new('somefile')
info = myfile.stat
t1 = info.mtime
t2 = info.atime
t3 = info.ctime
Отметим, что объект File::Stat
возвращается методом класса (или экземпляра) stat
из класса File
. Метод класса lstat
(или одноименный метод экземпляра) делает то же самое, но возвращает информацию о состоянии самой ссылки, а не файла, на который она ведет. Если имеется цепочка из нескольких ссылок, то метод следует по ней и возвращает информацию о предпоследней (которая уже указывает на настоящий файл).
Для изменения времени доступа и модификации применяется метод utime
, которому можно передать несколько файлов. Время можно создать в виде объекта Time
или числа секунд, прошедших с точки отсчета.
today = Time.now
yesterday = today - 86400
File.utime(today, today, 'alpha')
File.utime(today, yesterday, 'beta', 'gamma')
Поскольку оба временных штампа изменяются одновременно, то при желании оставить один без изменения его сначала следует получить и сохранить.
mtime = File.mtime('delta')
File.utime(Time.now, mtime, 'delta')
10.1.11. Проверка существования и получение размера файла
Часто необходимо знать, существует ли файл с данным именем. Это позволяет выяснить метод exist?
из модуля FileTest
:
flag = FileTest::exist?('LochNessMonster')
flag = FileTest::exists?('UFO')
# exists? является синонимом exist?
Понятно, что такой метод не может быть методом экземпляра File
, поскольку после создания объекта файл уже открыт. В классе File
мог бы быть метод класса с именем exist?
, но его там нет.