Назад | Перейти на главную страницу

Как выполнить mv эквивалент да | cp -rf для каталогов?

Используя приведенное ниже дерево каталогов в качестве примера, как лучше всего переместить содержимое directory/folderA к directory.

Как перезаписать файл, если в месте назначения существует файл с таким же именем, например: directory/folderA/2017/06/info.log и directory/2017/06/info.log.

directory
|-- folderA
|   |-- 2017
|   |   |-- 06
|   |
|   |-- 2016
|   |   |-- 12
|   |   |-- 11
|   |   |-- 10
|
|-- 2017
|   |-- 04
|   |-- 05
|   |-- 06
|
|-- 2016
|   |

Вы можете добиться этого с помощью cp -l (--link, файлы жестких ссылок вместо копирования):

cp -rfl folderA .
rm -rf folderA

В mv просто перемещает, т.е. переименовывает каталог в ваш directory. Для перемещения файлов в одной файловой системе mv использует rename() системный вызов. Если источник и цель были в разных файловых системах, mv использовал бы cp и rm для выполнения перемещения, но сначала удаляет место назначения, копирует жестко связанные файлы (-R), но не следует по символическим ссылкам (-P):

rm -f destination_path && \
cp -pRP source_file destination && \
rm -rf source_file

Хотя вы не можете изменить это поведение mv, то cp Сама по себе команда более гибкая, и вам действительно стоит ее использовать. С участием cp, то -f вызывает удаление и создание отдельных файлов внутри места назначения вместо удаления сначала всего места назначения.

В cp также ограничен, поскольку он может либо перезаписывать (-f), хранитель (-n) или спросите (-i). Если вам нужно сравнить файлы, прежде чем решить, какой из них оставить, вам понадобится rsync.

Если вам все еще нужно использовать rename() системный вызов, но для достижения вашей цели по слиянию каталогов по желанию вам нужно будет написать сценарий, который вызывает отдельные rename()s для отдельных файлов.

Сначала я создал ваше дерево каталогов с помощью

[root@localhost /tmp]# mkdir -pv directory/folderA/2017/06 directory/folderA/2016/{10..12} directory/2017/{04..06} directory/2016

Затем я создал ваши файлы примеров с помощью:

[root@localhost /tmp]# touch directory/{,folderA}/2017/06/info.log

Наконец, я использовал rsync с параметром --delete-after для перемещения вместо поведения по умолчанию rsync, которое вместо этого создавало бы копию:

[root@localhost /tmp]# rsync --delete-after -a directory/folderA/ directory

Примечание: завершающий '/' после исходного каталога (т.е. каталог / folderA / в отличие от каталога / folderA) требуется, если вы хотите, чтобы каталоги были удалены после их копирования.

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

Вот пользовательская функция, которую вы можете добавить в свой ~ / .bashrc:

function mv() {
    if [[ "$@" =~ .*--delete-after.*-av*.* ]]; then
            rsync $@
    else
            command mv $@
    fi; }

Затем вызовите обновленный ~ / .bashrc, выйдя из системы и снова войдя в систему -или-, набрав:

[root@localhost /tmp]# exec bash

Теперь вы можете протестировать свою пользовательскую функцию с помощью:

[root@localhost /tmp]# mv --delete-after -av directory/folderA/ directory

чтобы получить подробный вывод,

или с:

[root@localhost /tmp]# mv --delete-after -a directory/folderA/ directory

получать только ошибки, если они обнаружены.

Кроме того, вы также можете избежать передачи yes команде cp -rf, введя команду cp с предшествующей обратной косой чертой, например:

[root@localhost /tmp]# \cp -rf directory/folderA/* directory/

Причина, по которой вы указываете да, заключается в том, что у вас, вероятно, есть псевдоним для команды cp в вашем ~ / .bashrc, например:

[root@localhost /tmp]# alias cp='cp -i'

что вы можете проверить, набрав:

[root@localhost /tmp]# type cp