- Data Structure
- Networking
- RDBMS
- Operating System
- Java
- MS Excel
- iOS
- HTML
- CSS
- Android
- Python
- C Programming
- C++
- C#
- MongoDB
- MySQL
- Javascript
- PHP
- Physics
- Chemistry
- Biology
- Mathematics
- English
- Economics
- Psychology
- Social Studies
- Fashion Studies
- Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Copy a directory to an existing directory Linux?
Overview
Copying files is one of the most common operations performed by using the Linux shell. We usually use the cp (copy) commands for this purpose.
We're going to discuss how to recursively move a folder to another location with or without overwriting.
Introduction to the Problem
We first need to understand what "Copy a folder to another location" means in this problem.
A good example can help you understand it better.
$ tree -a . ├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target └── originalTarget.file
3 directories, 4 files
Here, as shown in the output above, we have two directories under the src folder. There are some source code file and a sub−folder. We also have a.hidden.file.
We now need to copy the source folder into the destination folder.
We want the destination folder to be identical to the source folder.
├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── .hidden.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
However, if we just copy the contents of the source folder into the destination folder, we want everything under src to be recursively moved to the destination folder. We also want the original files under the destination to remain unchanged.
├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── .hidden.file ├── originalTarget.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
Since the target directory already exist, we cannot just use the cp −r src target method to do this task. Instead, we need to create a new directory called src inside the target directory first. Then, we can move the files from src into the newly created src directory.
After that, we’ll discuss how to achieve our objective by taking two different approaches −
Using cp command
Using rsync command
Using the cp Command
Let’s first take a look at how to fix the issue by using the cp command since that is fairly common.
cp Without Overwriting the target Directory
If the source folder is not empty, we cannot simply copy the contents of the source folder into the destination folder using the cp command.
However, cp has an −i option which treats the source as a regular file instead of a folder.
If we use the −rT option, then the cp command will recurse through the contents of the source folder and create copies of them in the target folder.
$ cp -rT src target $ tree -a . ├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── .hidden.file ├── originalTarget.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
4 directories, 7 files
tree‘s −a option tells us that we’re copying everything from the source directory into the destination directory. However, the source directory isn’t included in the copy operation. So we’re done!
Bash Globbing Trick
We've solved the issue by using the cp command with the −rT option.
We can solve the problem by copying everything from src into target. Therefore, we might be able to write the following: cp −r src/* target.
We can solve the problem by copying everything from src into target. Therefore, we might be able to write the following: cp -r src/* target.
$ cp -r src/* target $ tree -a . ├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── originalTarget.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
4 directories, 6 files
As the tree output indicates, most files under src were successfully transferred to the destination folder, except for the.dot file. This is because by using the ‘globstar’ option, the shell ignores any filename beginning with a period (“.“).
There are two ways to solve this problem. One solution is to modify the global settings so that the globbing includes.dot files. You can use the shopt −s dotglob command for that.
$ ( shopt -s dotglob; cp -r src/* target ) $ tree -a target target ├── .hidden.file ├── originalTarget.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
1 directory, 4 files
$ shopt dotglob
dotglob off
We can see from the output above that the dot file has also been successfully created. Also, we wrap our shoptcp commands together with the cp commands in parentheses (…) so they run in a subshell because we want the shoptcp commands to only effect the single cp commands.
After the command executes, when we check the globbing options, they're still disabled.
It's easy enough to change bash's default behavior. But, if you're writing scripts for yourself, it might be inconvenient. Particularly, if you want to avoid unintended consequences.
You could also add.dotfiles to your source control system by using "src/." instead of "src/*".
Let’s take a look at whether it worked as we expected.
$ cp -r src/. target $ tree -a target target ├── .hidden.file ├── originalTarget.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
1 directory, 4 files
cp and Overwrite the target Directory
If we want to replace the contents of the source folder with the contents of the target folder, then it's easier to use the −R option instead of the −O option. So let's first remove the target folder and run a cp −r command.
$ rm -r target && cp -r src target $ tree -a . ├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── .hidden.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
4 directories, 6 files
Using the rsync Command
rsync is a useful tool for solving this issue.
rsync Without Overwriting the target Directory
There are two rsync command lines that we can use to copy a directory recursively −
rsync −a source target: copies the contents of the source into target
rsync −a src/ target− copy the contents of the src directory into target
The two commands above are almost identical. The one with the leading slash is exactly what we're looking for.
Let's test it out on our example −
$ rsync -a src/ target $ tree -a . ├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── .hidden.file ├── originalTarget.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
4 directories, 7 file
The tree’s results show that the command has solved our issue.
rysnc and Overwrite the target Directory
We've learned we can combine two command lines, "sudo rmdir /path/to/folder && sudo cp −r /source/folder /path/to/destination" to solve the problem.
With rsync, we can achieve it all at once −
$ rsync -a --delete src/ target $ tree -a . ├── src │ ├── .hidden.file │ ├── srcFile.txt │ └── subSrc │ └── subSrcFile.txt └── target ├── .hidden.file ├── srcFile.txt └── subSrc └── subSrcFile.txt
4 directories, 6 files
After executing the rsync commands, both target and source contain the same content. We've thus found an alternative solution to our original problem.
The secret to this solution is the −delete switch.
The −delete option tells rsync to delete any file from target/ that isn't present in source/, ensuring that both source and target end up identical at the end of the transfer.
Conclusion
We've discussed how to recursively move a folder into another folder with or without overwriting.
We've learned two ways to solve the problem: by using the common cp (copy) and rsync commands.
We've talked about bash's dotglob setting and how it affects globbing behavior.