- Copy and overwrite directory recursively
- 3 Answers 3
- Copy a Directory in Linux – How to cp a Folder in the Command Line in Linux and Unix (MacOS)
- How to copy a file to the current directory
- How to copy a file to another directory
- How to copy multiple files to a directory
- How to copy a directory to another directory
- How to copy the entire directory vs the contents of the directory
- How to prevent overwriting files with cp
- The interactive flag
- The no-clobber flag
- Other options
- How to force ‘cp’ to overwrite directory instead of creating another one inside?
- 10 Answers 10
- How can I recursively copy a directory into another and replace only the files that have not changed?
- 3 Answers 3
- How to replace all the contents from one folder with another one
- 3 Answers 3
Copy and overwrite directory recursively
I have a directory called ‘existing_folder’ and another directory called ‘temp’ I want to replace the contents of ‘existing_folder’ with those of ‘temp’ along with any sub directories. Because the directory contains web pages, this has to be done in a way that ensures minimal downtime. Is there a way to do this? What command should I use to achieve this?
3 Answers 3
Have you tried rsync ?
From your requirements I think it is the best tool. It will replace only the files that changed, copy new ones and it can remove those that are gone in origin.
$ rsync -av --delete temp/ existing_folder/
Notice the slash after temp, it is required because you want to sync the contents. Without it it would create a directori temp inside existing folder.
The delete argument makes the files that are no longer in temp be removed in existing_folder.
You can also do a dry-run if you add -n argument. It will tell you what changes will be done without doing anything.
I found this to be a better solution. Using the -p -o and -g flags I was able to keep the permissions, owner and group
If both orig_folder and temp are on the same physical hard drive, renaming (moving) them is essentially instantaneous. That means you could simply do
mv orig_folder foo && mv temp orig_folder && rm -rf foo
That will rename orig_folder to foo , then rename temp to orig_folder and finally delete foo . On the same filesystem, the two mv operations will take next to no time (0.004 seconds on my system).
If the source and target directories are not on the same file system, in order to minimize the time that the files are not available, you would first need to move the source directory to the same filesystem and then rename:
mv /path/to/temp . && mv orig_folder foo && mv temp orig_folder && rm -rf foo
Copy a Directory in Linux – How to cp a Folder in the Command Line in Linux and Unix (MacOS)
To copy files or directories in Unix-based operating systems (Linux and MacOS), you use the cp command.
The cp command is a relatively simple command, but its behavior changes slightly depending on the inputs (files vs directories) and the options you pass to it.
To view the documentation or manual for the cp command, run man cp at your terminal:
$ man cp NAME cp -- copy files SYNOPSIS cp [OPTIONS] source_file target_file cp [OPTIONS] source_file . target_directory .
The basic form of this command takes an input source (or sources) that you want to copy (files or directories) and a destination to copy the files or directories to:
cp [OPTIONS] source_file target_file
How to copy a file to the current directory
To copy a file, pass the file you want to copy and the path of where you want to copy the file to.
If you have a file named a.txt , and you want a copy of that file named b.txt :
$ ls a.txt $ cp a.txt b.txt $ ls a.txt b.txt
By default the cp command uses your current directory as the path.
How to copy a file to another directory
To copy a file to a directory that is different from your current directory, you just need to pass the path of the other directory as the destination:
$ ls ../directory-1/ $ cp a.txt ../directory-1/ $ ls ../directory-1/ a.txt
After the cp command, the previously empty directory-1 now contains the file a.txt .
By default the copied file receives the name of the original file, but you can also optionally pass a file name as well:
$ cp a.txt ../directory-1/b.txt $ ls ../directory-1/ b.txt
How to copy multiple files to a directory
To copy more than one file at a time you can pass multiple input sources and a directory as destination:
$ ls ../directory-1/ $ cp first.txt second.txt ../directory-1/ $ ls ../directory-1/ first.txt second.txt
Here the two input sources ( first.txt and second.txt ) were both copied to the directory directory-1 .
How to copy a directory to another directory
If you try to pass a directory as the input source, you get this error:
$ cp directory-1 directory-2 cp: directory-1 is a directory (not copied).
To copy a directory, you need to add the -r (or -R ) flag—which is shorthand for —recursive :
$ ls directory-1 a.txt $ cp -r directory-1 directory-2 $ ls directory-1 directory-2 $ ls directory-2 a.txt
Here directory-1 containing the file a.txt is copied to a new directory called directory-2 —which now also contains the file a.txt .
How to copy the entire directory vs the contents of the directory
There is an interesting edge case when you copy a directory: if the destination directory already exists, you can choose whether to copy the contents of the directory or the entire directory by adding or removing a trailing / from your input.
Here’s the description from the -R option of the man page:
If source_file designates a directory, cp copies the directory and the entire subtree connected at that point. If the source_file ends in a /, the contents of the directory are copied rather than the directory itself.
If you want to copy just the contents of the directory into another directory, add a trailing / to your input.
If you want to copy the contents of the directory and the directory folder itself into another directory, don’t add a trailing / :
$ ls directory-1 directory-2 $ ls directory-2 $ cp -r directory-1 directory-2 $ ls directory-2 directory-1 $ ls directory-2/directory-1 a.txt
Here you can see that because directory-2 already exists—and the input source didn’t have a trailing / —both the contents of directory-1 and the directory itself was copied into the destination.
How to prevent overwriting files with cp
By default, the cp command will overwrite existing files:
$ cat a.txt A $ cat directory-1/a.txt B $ cp a.txt directory-1/a.txt $ cat directory-1/a.txt A
There are two ways to prevent this.
The interactive flag
To be prompted when an overwrite is about to occur, you can add the -i or —interactive flag:
$ cp -i a.txt directory-1/a.txt overwrite directory-1/a.txt? (y/n [n])
The no-clobber flag
Or, to prevent overwrites without being prompted, you can add the -n or —no-clobber flag:
$ cat a.txt A $ cat directory-1/a.txt B $ cp -n a.txt directory-1/a.txt $ cat directory-1/a.txt B
Here you can see that thanks to the -n flag the contents of directory-1/a.txt were not overwritten.
Other options
There are many other useful options to pass to the cp command: like -v for «verbose» output or -f for «force.»
I highly encourage you to read through the man page for all of the other useful options.
If you liked this tutorial, I also talk about topics like this on Twitter, and write about them on my site.
How to force ‘cp’ to overwrite directory instead of creating another one inside?
I’m trying to write a Bash script that will overwrite an existing directory. I have a directory foo/ and I am trying to overwrite bar/ with it. But when I do this:
a new bar/foo/ directory is created. I don’t want that. There are two files in foo/ ; a and b . There are files with same names in bar/ as well. I want the foo/a and foo/b to replace bar/a and bar/b .
10 Answers 10
You can do this using -T option in cp .
See Man page for cp .
-T, --no-target-directory treat DEST as a normal file
So as per your example, following is the file structure.
$ tree test test |-- bar | |-- a | `-- b `-- foo |-- a `-- b 2 directories, 4 files
You can see the clear difference when you use -v for Verbose.
When you use just -R option.
$ cp -Rv foo/ bar/ `foo/' -> `bar/foo' `foo/b' -> `bar/foo/b' `foo/a' -> `bar/foo/a' $ tree |-- bar | |-- a | |-- b | `-- foo | |-- a | `-- b `-- foo |-- a `-- b 3 directories, 6 files
When you use the option -T it overwrites the contents, treating the destination like a normal file and not directory.
$ cp -TRv foo/ bar/ `foo/b' -> `bar/b' `foo/a' -> `bar/a' $ tree |-- bar | |-- a | `-- b `-- foo |-- a `-- b 2 directories, 4 files
This should solve your problem.
just in case anyone is tripped up by this it won’t work with OSX cp developer.apple.com/library/mac/documentation/Darwin/Reference/…
It’s not clear that this answer is what the OP is looking for, although the examples given above mask the problem. With the -T option, files that are in an existing target ( bar/ ) but not in the source ( foo/ ) will be left in place, so this is not what most people would consider a complete overwrite of the directory. ie. if bar/baz existed already, it would still exist afterwards.
This answer does answer the op question, but doesn’t address the case of if the destination already exists and you want to remove contents it contains but the source directory does not. This is not an expected behavior of copying files from one place to the other. It only overwrites in the target things that are also in the source, it doesn’t touch anything in the target that is not in the source. You can clean the target folder by prepending a command to do it: rm -rf bar/* && cp -TRv foo/ bar/
I’m not a mind reader. I don’t see further clarification what the OP was looking for, but this was DEFINITELY the answer that I (MEEEE) was looking for
How can I recursively copy a directory into another and replace only the files that have not changed?
The export directory contains many of the same files/folders that the root does, however the root contains additional ones not found in export.
I’d like to merge all of the contents of export with my webroot with the following options:
- Overwriting the file in webroot if export’s version contains different code than what is inside of webroot’s version (live)
- Preserve the permissions/users/groups of the file if it is overwritten (the export version replacing the live version) *NOTE I would like the webroots permissions/ownership maintained, but with export’s contents
- No prompting/stopping of the copy of any kind (ie not verbose)
- Recursive copy — obviously I would like to copy all* files folders and subfolders found in export
I’ve done a bit of research into cp — would this do the job?:
cp -pruf ./export /path/to/webroot
Note that your first criterion is not clear cut. The answers mostly assume you mean ‘if the file in webroot is newer than the file in export, leave it alone’. If you truly mean ‘compare contents and copy export version if there is a difference’, then simply copy everything . continued.
. continuation. as the new files will appear, and the old files that are the same in both will still be the same after the copy — except perhaps for the modification time.
3 Answers 3
It might, but any time the corresponding files in export and webroot have the same content but different modification times, you’d wind up performing an unnecessary copy operation. You’d probably get slightly smarter behavior from rsync :
rsync -pr ./export /path/to/webroot
Besides, rsync can copy files from one host to another over an SSH connection, if you ever have a need to do that. Plus, it has a zillion options you can specify to tweak its behavior — look in the man page for details.
EDIT: with respect to your clarification about what you mean by preserving permissions: you’d probably want to leave off the -p option.
How to replace all the contents from one folder with another one
I have folders old and new . I want to replace all the contents in old/* to new/* . There can be many subdirectories in those folders. But there can be few files which are not in new/* but are in old/* , so I want them to stay as they are. How can I do that from a Linux shell?
3 Answers 3
rsync would probably be a better option here. It’s as simple as rsync -a subdir/ ./. check this unix.stackexchage answer for better solutions
use -f with the cp command
suppress cp to overwrite» prompt..
To override cp’s alias you can simply enclose it in quotes:
for more information follow these links:
Don’t use rsync for a one time copy, the overhead of hashing all dir contents is substantial, it only pays when keeping directories synchronized. For a gigantic one time copy, use a tarpipe.
Use rsync . It will synchronize the directories in one direction. So, if you want to update your old folder with everything from new , but keep what’s in there, just use:
rsync -avh --dry-run /path/to/new/ /path/to/old/
This will, in a first instance, just output the list of files that would be transferred. In that case: Everything found in new will be copied to old , unless it’s already there. Everything in old stays as it is.
If it looks fine to you, remove the —dry-run argument to transmit them for real.
The -avh flags just enable archive mode (which will preserve timestamps, etc.), verbosity and human-readable file-sizes. Nothing will be deleted from the destination unless you specify the —delete flag. Consult man rsync for more information.