Введение в POSIX'ивизм

       

Манипулирование файлами


Начнем с копирования - это выполняется очень простой командой, cp, имеющей, однако, весьма разнообразные аспекты применения. В самом простом своем виде она требует всего двух аргументов - имени файла-источника на первом месте и имени целевого файла - на втором:

$ cp file_source file_target

Этим в текущем каталоге создается новый файл (file_target), идентичный по содержанию копируемому (file_source). То есть область данных первого будет дублировать таковую последнего. Однако области метаданных у них будут различны изначально. Целевой файл - это именно новый файл, со своим идентификатором inode, заведомо иными временными атрибутами; его атрибуты доступа и принадлежности в общем случае также не обязаны совпадать с таковыми файла-источника.

Новый файл может быть создан и в произвольном каталоге, к которому пользователь имеет соответствующий доступ: для этого следует только указать полный путь к нему:

$ cp file_source dir/subdir/file_target

Если в качестве второго аргумента команды указано просто имя каталога, то новый файл будет создан в нем с именем, идентичным имени файла-источника. Однако подчеркну, что в любом случае копирования создается именно новый файл, никак после этого не связанный с файлом исходным.

Если в качестве последнего аргумента выступает имя каталога, он может предваряться любым количеством аргументов - имен файлов:

$ cp file1 file2 ... file3 dir/

В этом случае в целевом каталоге dir/ будут созданы новые файлы, идентичные по содержанию файлам file1, file2 и т.д.

Если в целевом (или текущем) каталоге уже имеется файл с именем, совпадающим с именем вновь создаваемого файла, он в общем случае будет без предупреждения заменен новым файлом. Единственное средство для предотвращения этого - задание опции -i (от interactive) - при ее наличии последует запрос на перезапись существующего файла:

$ cp -i file1 file2 overwrite file2? (y/n [n])

Как будет показано в главе о командных оболочках, многие из них могут быть настроены так, чтобы по умолчанию не допускать перезаписи существующих файлов без запроса.


Однако если такая потребность осознанно возникнет (например, при удалении большого количества заведомо ненужных файлов), это можно выполнить с помощью опции -f (от force).

Имя каталога может выступать и в качестве первого аргумента команды cp. Однако это потребует опции -R (иногда допустима и опция -r - в обоих случаях от recursive). В этом случае второй аргумент также будет воспринят как имя каталога, который не только будет создан при этом, но в нем также будет рекурсивно воспроизведено содержимое каталога источника (включая и вложенные подкаталоги).

При копировании файлов, представляющих собой символические ссылки, они будут преобразованы в регулярные файлы, копирующие содержимое файлов - источников ссылки. Однако при рекурсивном копировании каталогов, содержащих символические ссылки, возможно их воспроизведение в первозданном виде - как симлинков. Для этого вместе с опцией -R должна быть указана одна из опций -H или -L. Однако обе они при отсутствии -R игнорируются.

Как уже было сказано, создаваемые при копировании целевые файлы по умолчанию получают атрибуты доступа и времени, не зависящие от таковых файла-источника. Обычно они определяются значением аргумента команды umask, заданной глобально, в профильном файле командной оболочки пользователя (по умолчанию значение umask обычно - 022). Однако при желании атрибуты исходного файла можно сохранить в файле целевом - для этого предназначена опция -p. Разумеется, атрибуты эти будут сохранены только в том случае, это это допустимо целевой файловой системой: не следует ожидать, что атрибуты доступа и принадлежности будут сохранены при копировании на носитель с файловой системой FAT.

Для выполнения операции копирования файла он должен иметь атрибут чтения для пользователя, выполняющего копирование; кроме того, последний должен обладать правом на изменение каталога, в который производится копирование.

Кроме простого копирования файлов, существует команда для копирования с преобразованием - dd. Обобщенный ее формат весьма прост:



$ dd [options]

то есть она просто копирует файл стандартного ввода в файл стандартного вывода, а опции описывают условия преобразования входного потока данных в выходной. Реально основными опциями являются if=file1, подменяющая стандартный ввод указанным файлов, и of=file2, проделывающая ту же операцию со стандартным выводом.

А далее - прочие условия преобразования, весьма обильные. Большинство из них принимают численные значения в блоках:

  • опции ibs=n и obs=n устанавливают размер блока для входного и выходного потоков, bs=n - для обоих сразу;


  • опция skip=n указывает, сколько блоков нужно пропустить перед записью входного потока;


  • опция count=n предписывает скопировать из входного потока лишь указанное количество блоков, отсчитываемых с начала файла-источника.


  • Имеется и опция conv=value, которая преобразует входной поток в соответствие с принятыми значениями, например, из формата ASCII в формат EBCDIC, рекомендуемый для использования в ОС на базе Unix System V.

    Сфера применения команды dd далеко выходит за рамки простого копирования файлов. Например, именно с ее помощью изготавливаются загрузочные дискеты, точные копии CD в файловой системе на винчестере, преобразуются шрифтовые файлы из одного формата в другой, и еще многое. В частности, эта же команда может применяться для резервного копирования данных, в том числе и на CD. И потому мы еще обратимся к ней в соответствующем параграфе этой главы.

    Наконец, в операционках BSD-клана существует еще и команда cpdup, призванная копировать не просто файлы, а целые файловые системы. В отличие от команды cp, с ее помощью создается полное зеркало файловой системы или отдельных ее ветвей, с сохранением жестких и символических ссылок, файлов устройств, временных атрибутов и атрибутов доступа файлов и подкаталогов. Именно команда cpdup используется при установке DragonFlyBSD для переноса структуры установочного CD на носитель, выбранный в качестве цели инсталляции (что описано в соответствующем цикле). Другое применение этой команды - резервное копирование, и в посвященном ему параграфе мы рассмотрим ее подробнее.



    Следующие две часто используемые файловые операции - переименование и перемещение, - выполняются одной командой, mv. Она требует минимум двух аргументов - имени источника и целевого имени. Если оба они - имена файлов, происходит переименование первого файла во второй. Если последним аргументом выступает имя уже существующего каталога, то файл или каталог, указанные в качестве первого аргумента, перемещается в каталог назначения. Причем если первый аргумент - файл, между первым и последним аргументами может быть сколько угодно аргументов - имен файлов (но не каталогов).

    Как и при копировании, при перемещении и переименовании одноименные файлы, ранее существовавшие в целевом каталоге, затираются, замещаясь файлами-источниками без предупреждения. Чтобы этого не случилось, используется опция -i, требующая запрос на подтверждение действия. Напротив, опция -f в принудительном порядке перезаписывает существующий файл.

    Операции копирования и перемещения/переименования выглядят сходными, однако по сути своей глубоко различны. Начать с того, что команда mv не совершает никаких действий с перемещаемыми или переименовываемыми файлами - она модифицирует каталоги, к которым приписаны имена этих файлов. Это имеет два важных следствия. Во-первых, при перемещении/переименовании файлы сохраняют первозданными атрибуты доступа, принадлежности и даже времени изменения метаданных (ctime) и модификации данных (mtime) - ведь ни те, ни другие при перемещении/переименовании файла не изменяются.

    Во-вторых, для выполнения этих действий можно не иметь никаких вообще прав доступа к файлам - достаточно иметь право на изменение каталогов, в которых они переименовываются или перемещаются: ведь имя файла фигурирует только в составе каталога, и нигде более.

    Аналогичный смысл имеет и удаление файлов, выполняемое командой

    $ rm filename

    в которой аргументов, означающих имена подлежащих удалению файлов, может быть произвольное количество. Как и при перемещении, при этом не затрагиваются ни метаданные, ни данные файлов, а только удаляются их имена из родительских каталогов.


    И потому для удаления файлов опять же не обязательно иметь какие-либо права в их отношении - достаточно прав на изменение содержащих их каталогов.

    Командой rm файлы-аргументы будут удалены в общем случае без предупреждения. Подобно командам cp и mv, для команды rm предусмотрены опции -i (запрос на подтверждение) и -f (принудительное удаление вне зависимости от настроек оболочки).

    Интересный момент - удаление случайно созданных файлов с именами, "неправильными" с точки зрения системы или командной оболочки. Примером этого могут быть имена, начинающиеся с символа дефиса. Если попробовать сделать это обычным образом

    $ rm -file

    в ответ последует сообщение об ошибке типа

    rm: illegal option -- l

    то есть имя файла будет воспринято как опция. Для предотвращения этого такое "неправильное" имя следует предварить символом двойного дефиса и пробелом, означающими конец списка опций:

    $ rm -- -file

    В принципе, команда rm ориентирована на удаление обычных и прочих файлов, но не каталогов. Однако с опцией -d она в состоянии справиться и с этой задачей - в случае, если удаляемый каталог пуст. Наконец, опция -R (или -r) производит рекурсивное удаление каталогов со всеми их файлами и вложенными подкаталогами.

    Это делает использование опции -R весьма опасным: возможно, набивший оскомину пример

    $ rm -R /

    когда при наличии прав суперпользователя уничтожается вся файловая система, и утрирован, но в локальном масштабе такая операция более чем реальна.

    Специально для удаления каталогов предназначена команда

    $ rmdir

    которая способна удалить только пустой каталог. Кроме того, с опцией -p она может сделать это и в отношении каталогов родительских - но также только в том случае, если они не содержат файлов.


    Содержание раздела