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
replace a whole file with another file in bash
Ive learned how to replace a line using bash script but I am wanting to learn how to replace a whole file with another file in a different folder with the same name. Is this possible??
4 Answers 4
cp -f [original file] [new file]
Copies the original file and overwrites the target file (hence -f which stands for «force»).
Looks like you switched up the arguments, It should be the other way around. cp -f [new file] [original file]
In case you are attempting to copy just the content of the file try
cat /first/file/same_name > /second/file/same_name
This will overwrite all the content of the second file with the content from the first. However, your owner, group, and permissions of the second file will be unchanged.
«overwrite content» and «copy» are kinda different operations if the destination file is a symlink 🙂
This is exactly what I needed to deal with hardlinked files updated in a way the caused the link to be broken (saved as a separate file.)
If file2 does not exist, then file1 is renamed file2. If file2 exists, its contents are replaced with the contents of file1.
Like above however, since the «-i» (interactive) option is specified, if file2 exists, the user is prompted before it is overwritten with the contents of file1.
mv file1 file2 file3 dir1
The files file1, file2, file3 are moved to directory dir1. dir1 must exist or mv will exit with an error.
If dir2 does not exist, then dir1 is renamed dir2. If dir2 exists, the directory dir1 is created within directory dir2.
Copy a file and overwrite the existing file
I have two images (image1.png and image2.png) in the same folder on my server, I want to run a command that overwrites image2.png to image1.png. I prefer to overwrite the image instead of deleting it and then replace it by the other one. How can I achieve that via ssh command line?
3 Answers 3
ssh host "cd path/to/directory && cp image1.png image2.png"
The && is safer than ; in case the cd fails, e.g. because of a typo: in such a case, the cp won’t be executed instead of possibly copying a wrong file.
@1_CR The OP didn’t say that he wanted to remove image1.png . But he can use mv if this gives the behavior he wants.
@Minalsaac — you have to elevate permissions — if you can. ssh -t . ‘cd $path && sudo cp ./file1 ./file2’ — but it might be better if you just logged on to a priveleged account initially when connecting with ssh in the first place.
Without sudo the command ssh server «cd path/to/directory && cp image1.png image2.png» doesn’t have privileges to chmod the permissions.
But with sudo it would, but being run after ssh , it never gets password input for it on the remote server, so the solution is use -S and pipe a password for sudo as follows:
ssh server » cd path/to/directory && echo sudo_password | sudo -S chmod 600 image2.png && cp image1.png image2.png»
However, how @terdon marked, we don’t need to change permissions here, but use sudo cp ,so it comes to:
ssh server » cd path/to/directory && echo sudo_password | sudo -S cp image1.png image2.png»
or (in case you think that your password can be read)
ssh server -t » cd path/to/directory && sudo cp image1.png image2.png»
UPDATE: also @terdon warned and I added this, because I think it’s important to stress and make an accent on such possible realization:
I really would remove this suggestion of using -S, it is not needed and very dangerous (see @mikserv’s comments and my answer). It is also pointless. The only «advantage» you mention, that of being able to pipe is a fringe case and in most situations you could just pipe on the server instead. You can also use sshpass as you suggested or set up passwordless sudo. All sorts of ways that don’t store a server’s password as plaintext. – terdon
On the one hand this is good for the automation with no getting sudo password promts and, to have completely automated code/script you would add sshpass -p password ssh. .
However on the server where others can easily read your sudo password provided as open text during the ssh session that’s not recommended from the security perspectives. So, to have a sudo with ssh and be safe use ssh -t
ssh -t server «cd path/to/directory && sudo chmod 600 image2.png && cp image1.png image2.png»
Nevertheless, with -t it’s impossible to pipe ssh «sudo command»| command for example ssh -t server «cd path/to/directory && sudo»|grep «text» but it IS possible with ussage of -S and echoing password, e.g. ssh server ‘echo password | sudo -S ls -l’| grep ‘a’