Linux – How to perform the mv equivalent of yes | cp -rf on directories

bashcommand-line-interfacefilesystemslinuxmv

Using the below directory tree as an example, what is the best way to move the contents of directory/folderA to directory.

How to overwrite a file if a file with the same name exists in the destination, for example: directory/folderA/2017/06/info.log and directory/2017/06/info.log.

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

Best Answer

You can achieve this with cp -l (--link, hard link files instead of copying):

cp -rfl folderA .
rm -rf folderA

The mv just moves i.e. renames the directory to be your directory. For moving files within the same file system mv uses rename() system call. If the source and target were on different files systems, mv would use cp and rm to accomplish the move, but still first removes the destination, copies hard linked files (-R) but doesn't follow symbolic links (-P):

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

While you can't change this behavior of mv, the cp command itself is more flexible, and you really should use it, instead. With cp, the -f causes removing and creation of single files inside the destination instead of removing the whole destination first.

The cp is also limited as it can only either overwrite (-f), preserver (-n) or ask (-i). If you need to compare the files before deciding which one to keep, you'd need rsync.

If you still need to use rename() system call but accomplish your goal of merging the directories as desired, you'd need to write a script that invokes individual rename()s for single files.