Заменить папку другой папкой с помощью mv (без предварительного удаления целевой папки)

#bash #shell #command-line #mv

#bash #оболочка #командная строка #mv

Вопрос:

Я пытаюсь получить directory замену существующей folder , но не могу сделать это с помощью mv — я верю, что есть способ, и я просто не знаю его (пока). Даже после просмотра справочной страницы и поиска в Интернете.

Если /path/to/ только содержит directory , следующая команда переместится /path/to/directory (исчезнет) в /path/to/folder

 mv /path/to/directory /path/to/folder
  

По сути, это переименование, чего я и пытаюсь добиться.

Но если /path/to/folder она уже существует, та же команда перемещает папку /path/to/directory в /path/to/folder/directory .

Я не хочу использовать cp команду, чтобы избежать ввода-вывода.

Комментарии:

1. Может быть: { rm -rf /path/to/folder; mv /path/to/directory /path/to/folder; }

2. Я знаю, что мог бы сначала переместить цель вот так mv folder moved amp;amp; mv directory folder amp;amp; rm -r moved , но я думаю, что это ненужный взлом и оставил бы меня в ситуации, когда папка не существует — чего я хочу избежать.

3. Ярлыка нет; существуют фундаментальные различия между каталогами и файлами, и вы не можете перезаписать одну папку другой подобным образом за один шаг. Однако важный вопрос заключается в том, почему это имеет значение, если /path/to/folder на данный момент не существует?

4. Предполагая, что оба folder и directory находятся в одной файловой системе, вы можете просто использовать ln вместо cp для минимизации ввода-вывода ln /path/to/directory/* /path/to/folder amp;amp; rm -rf /path/to/directory ..

5. Короче говоря, ln <source> <target> создайте новую запись каталога <target> , которая ссылается на тот же базовый файл, что и <source> . Ни одно из имен не является более «реальным», чем другое; оба ссылаются на файл с количеством ссылок, равным 2. Фактически, rm на самом деле файл не удаляется; он просто удаляет ссылку на файл. Файловая система обрабатывает файлы для сбора мусора, на которые больше нет ссылок.

Ответ №1:

Вместо того, чтобы использовать cp для фактического копирования данных в каждом файле, используйте ln для создания «копий» указателей на файл.

 ln /path/to/directory/* /path/to/folder amp;amp; rm -rf /path/to/directory
  

Обратите внимание, что это немного более атомарно, чем использование cp ; каждый отдельный файл появляется в /path/to/folder за один шаг (т. Е. нет никаких шансов, что /path/to/folder/foo.txt он когда-либо будет частично скопирован), но все еще есть небольшое окно, в котором некоторые, но не все файлы из /path/to/directory были связаны с folder . Кроме того, rm -rf не является атомарным, но, предполагая, что это никого не интересует directory , это не проблема. (Хотя, поскольку файлы из /path/to/directory разорваны, вы можете увидеть изменения в количестве ссылок для файлов в разделе /path/to/foldoer , которые меняются с 2 на 1. Маловероятно, что кого-то это будет волновать.)


То, что вы считаете файлом, на самом деле просто запись файловой системы в анонимный файл, управляемый файловой системой. Для примера рассмотрим простой пример.

 $ mkdir d
$ cd d
$ echo hello > file.txt
$ cp file.txt file_copy.txt
$ ln file.txt file_link.txt
$ ls -li
total 24
12890456377 -rw-r--r--  2 chepner  staff  6 Mar  3 12:46 file.txt
12890456378 -rw-r--r--  1 chepner  staff  6 Mar  3 12:47 file_copy.txt
12890456377 -rw-r--r--  2 chepner  staff  6 Mar  3 12:46 file_link.txt
  

-i Опция добавляет номер индекса каждой записи (первый столбец) к выходным данным; индекс можно рассматривать как уникальный идентификатор файла. В этом выводе вы можете видеть, что file_copy.txt это совершенно новый файл с индексом, отличным от file.txt . file_link.txt имеет точно такой же индекс, что означает, что file.txt и file_link.txt — это просто два разных имени для одного и того же объекта. Число непосредственно перед владельцем — это количество ссылок; file.txt и file_link.txt оба ссылаются на файл с количеством ссылок, равным 2.

При использовании rm вы просто удаляете ссылку на файл, а не сам файл. Файл не удаляется до тех пор, пока количество ссылок не уменьшится до 0. Для демонстрации мы удалим file.txt и file_copy.txt .

 $ rm file.txt file_copy.txt
$ ls -li
total 8
12890456377 -rw-r--r--  1 chepner  staff  6 Mar  3 12:46 file_link.txt
  

Как вы можете видеть, единственная ссылка на file_copy исчезла, поэтому индекс 12890456378 больше не отображается в выходных данных. (Действительно ли данные исчезли, зависит от реализации файловой системы.) file_link.txt , однако, по-прежнему ссылается на тот же файл, что и раньше, но теперь с количеством ссылок 1, потому что file.txt был удален.

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