В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13 |
Организация файловой системы
Выше мы отмечали, что, как правило, файлы создаются по мере необходимости при выполнении определенных операций. Одной из таких операций является копирование файлов, выполняемое служебной программой cp:
cp [-fip] исходный_файл целевой_файл cp [-fip] исходный_файл ... целевой_каталог cp -R [-H | -L | -P] [-fip] исходный_файл ... целевой_каталог
В двух первых формах утилита cp напоминает ln, только наряду с возможным созданием новых ссылок создаются и новые файлы и, в любом случае, копируется содержимое исходных (или указуемых исходными, если последние представляют собой символьные ссылки ) файлов.
При наличии опции -R выполняется рекурсивное копирование исходных файловых иерархий в целевой каталог со стандартной трактовкой символьных ссылок, управляемой опциями -H, -L и -P (см. выше, например, описание утилиты chown ). Если копирование производится в существующий каталог, имена копий образуются как конкатенация целевого каталога, символа / и маршрута относительно каталога, содержащего исходный_файл. Если в командной строке заданы два файла и целевой не существует, он создается и становится корнем иерархии-копии, то есть исходный_файл копируется непосредственно в него, а маршруты файлов нижележащих уровней считаются относительно исходного_файла.
Если в командной строке задано более двух файлов и целевой не существует или не является каталогом, это считается ошибкой.
Опция -i влечет запрос подтверждения перед попыткой копирования в существующий файл.
По опции -f, если не удается открыть целевой файл, делается попытка сначала удалить его, а затем продолжить действия по копированию.
Опция -P вызывает копирование не только содержимого, но и атрибутов исходных файлов ( режима, идентификаторов владельца и владеющей группы, времени последнего доступа и изменения).
Синтаксис, с точностью до опций аналогичный двум первым формам cp, имеет вызов служебной программы перемещения файлов mv:
mv [-fi] исходный_файл целевой_файл mv [-fi] исходный_файл ... существующий_целевой каталог
Формально можно считать, что она выполняет копирование иерархий с корнями в исходных_файлах (без раскрытия символьных ссылок и с копированием атрибутов файлов) и уничтожает оригиналы. Отметим, что в первой форме mv целевой_ файл может не существовать, а исходный - являться каталогом ; в любом случае на месте целевого каталога допускается использование символьной ссылки на него.
На самом деле утилита mv, как правило, применяется для переименования файлов, и тогда ее работа сводится к созданию новых элементов каталогов и уничтожению старых, а реальное копирование может потребоваться только при перемещении файлов между файловыми системами (например, со съемного носителя на постоянный).
По опции -i запрашивается подтверждение перед замещением существующего файла, опция -f влечет отсутствие подобных запросов (по поводу логики запроса подтверждений см. выше описание команды rm ).
Приведем пример употребления утилиты mv. Пусть текущий каталог содержит только файлы x и y и пустой каталог d1 (см. листинг 4.43). Тогда после выполнения команд, показанных в листинге 4.44, будет создан каталог d2, где окажутся файлы x и y, а каталог d1 исчезнет (см. листинг 4.45).
.: d1/ x y ./d1:Листинг 4.43. Состояние текущего каталога перед перемещением файлов.
ls -RF mv x y d1 mv d1 d2 ls -RFЛистинг 4.44. Использование утилиты mv для перемещения файлов и файловых иерархий.
.: d2/ ./d2: x yЛистинг 4.45. Состояние текущего каталога после перемещения файлов.
Продолжим этот пример двумя одинаковыми командами копирования (см. листинг 4.46).
cp -R d2 d1 cp -R d2 d1 ls -RFЛистинг 4.46. Применение утилиты cp для копирования файловых иерархий.
Первая команда скопирует иерархию с корнем d2 во вновь созданный каталог d1, вторая - под d1 (с сохранением имени d2 для корня копии). Результат показан в листинге 4.47.
.: d1/ d2/ ./d1: d2/ x y ./d1/d2: x y ./d2: x yЛистинг 4.47. Результат использования утилиты cp для копирования файловых иерархий.
Для перемещения (переименования) одного файла служит функция rename() из репертуара C99 (см. листинг 4.48).
#include <stdio.h> int rename (const char *old_path, const char *new_path);Листинг 4.48. Описание функции rename().
Функция rename() обладает частью функциональности служебной программы mv. Она не перемещает файловых иерархий и не раскрывает символьных ссылок, если их имена заданы в качестве аргументов. С другой стороны, rename() поддерживает переименование каталогов. В этом случае аргумент new_path не должен задавать файл другого типа, а если он задает существующий каталог, тот, по понятным причинам, должен быть пустым.
В продолжение двух предыдущих примеров продемонстрируем переименование каталогов (см. листинг 4.49). Итоговое состояние текущего каталога показано в листинге 4.50.
#include <stdlib.h> #include <stdio.h> #define OLD_DIR "d1/d2" #define NEW_DIR "d2" int main (void) { system ("rm -f " NEW_DIR "/*"); if (rename (OLD_DIR, NEW_DIR)) { perror ("RENAME failed"); return (-1); } system ("ls -RF"); return 0; }Листинг 4.49. Пример использования функции rename() для переименования каталогов.
.: d1/ d2/ ./d1: x y ./d2: x yЛистинг 4.50. Состояние текущего каталога после переименования каталогов с помощью функции rename().
Читателю предлагается оценить последствия повторного запуска приведенной программы.