-1

Okay so what I'm trying to do is that I have a file and I have to replace about 100 files in the location: /home/*/service*/files/ using that file recursively.

I used the following command:

cp -r File.txt /home/*/service*/files
cp: overwrite `/home/xxx/servicexxx/files/CustomCommands.txt'? y
cp: overwrite `/home/xxx/servicexxx/files/files/tips.txt'? ^C

Why is it creating a "files" folder inside a files folder instead of just replacing the already existing file. If I don't use the "-r" switch, it copies correctly but omits the other 99 directories showing "cp ommiting directory"

Secondly, I have to use the same method to replace a running binary file so that it would automatically switch to the new file next time the file is run. But I get this error:

cp: cannot create regular file `xxx': Text file busy
3
  • 1
    This is not going to work like this. You can copy one source to one destination or multiple sources to one directory, but not one source file to multiple destination files.
    – Sven
    Jul 18, 2013 at 10:42
  • I understand but why would it show the files copied correctly without the "-r" switch but just omit the rest of them. I actually have to replace 100 files with 1 file. Any shortcuts?
    – Asad Moeen
    Jul 18, 2013 at 11:00
  • Question fixed and answer added.
    – Asad Moeen
    Feb 23, 2014 at 9:37

3 Answers 3

3

You confusion here lies in how cp interprets arguments, and how shell expansion works. First, let's talk about shell expansion. Consider that you have a simplified directory/file structure that looks like:

/home/user1/service1/files/file1.txt
/home/user7/service100/files/file2.txt
/home/user22/service7/files/file3.txt

Now consider your command:

cp -r File.txt /home/*/service*/files

The shell will expand the second argument based on the files it can match before executing cp. You can see this working by replacing cp with echo. The actual command you are running is:

cp -r File.txt /home/user1/service1/files /home/user7/service100/files /home/user22/service7/files

The way the cp command works is to copy one or multiple sources into a single target, so what you're doing is copying the first three arguments into the last argument: /home/user22/service7/files.

Looking this all over again it explains exactly why your file is correctly copied to the last directory, and you get a smattering of cp: ommiting directory errors.

To achieve something like what you're looking to do, you could use a for loop:

for target in /home/*/service*/files/; do
    cp -v File.txt $target
done

The Text File Busy error is covered a bit in the link below and is probably an artifact of your flawed use of cp. I suspect a for loop like the above would be adequate for your binary replacement as well.

https://stackoverflow.com/questions/10638283/can-text-file-busy-happen-when-two-processes-trying-to-execute-a-perl-file-in

1
  • Semi colon missing after $target though.
    – Asad Moeen
    Jul 18, 2013 at 13:57
2

This is not going to work like this. You can copy one source to one destination or multiple sources to one directory, but not one source file to multiple destination files.

For the copy problem, employ the help of find, grep and xargs:

find /home -type f | grep \/home\/[[:alnum:]]+\/service[[:alnum:]]*\/ | xargs -l1 cp sourcefile 

but check first if all the right files are matched, eg. by removing the last pipe with the xargs.

0

I was able to get the second part working by using the "cp -f" option which did overwrite the running file. But I'm still not sure about the recursion issue.

Not the answer you're looking for? Browse other questions tagged .