6

I have to copy a set of files from one folder to another folder and I'm using the following command:

cp -rf `head -n 100 /home/tmp/abc.txt` /home/tmp/test/files

the file contents in abc.txt is like:

./folder1/example.tar.gz
./folder2/example.tar.gz
./folder3/example.tar.gz

But while executing the above cp command I'm getting:

cp: will not overwrite just-created `/home/tmp/test/files/example.tar.gz' with `./folder3 /example.tar.gz'
cp: will not overwrite just-created `/home/tmp/test/files/example.tar.gz' with `./folder1/example.tar.gz'

I can understand that because the name of the .gz files are the same that are showing in the error. What I want to do is to have the same folder structure inside /home/tmp/test/files as listed in abc.txt, like:

/home/tmp/test/files/folder1/example.tar.gz
/home/tmp/test/files/folder2/example.tar.gz
/home/tmp/test/files/folder3/example.tar.gz

But I'm getting only one example.tar.gz inside files folder after executing the above cp command.

So what is the way to get what I mentioned above?

6

cp won't work

Your example as it stands will not work because copy doesn't copy directory structures, it will only copy the files, hence the error message you're encountering. To do a deep copy such as this you can enlist either the tar command and use the construct tar cvf - --files-from=... | (cd /home/tmp/test/files/; tar xvf -) or you can just use rsync.

rsync

If I were you I'd use rsync to do this like so:

$ rsync -avz --files-from=abc.txt /src /home/tmp/test/files/.

If you only want the 1st 100 lines from file abc.txt you can do this:

$ rsync -avz --files-from=<(head -n 100 abc.txt) /src /home/tmp/test/files/.

Example

Sample folder data:

$ tree /home/saml/tmp/folder*
/home/saml/tmp/folder1
`-- example.tar.gz
/home/saml/tmp/folder2
`-- example.tar.gz
/home/saml/tmp/folder3
`-- example.tar.gz

Now copy the files:

$ rsync -avz --files-from=<(head -n 3 /home/saml/tmp/abc.txt) \
         /home/saml/tmp/. /home/saml/tmp/test/files/.
building file list ... done
./
folder1/
folder1/example.tar.gz
folder2/
folder2/example.tar.gz
folder3/
folder3/example.tar.gz

sent 3147093 bytes  received 81 bytes  6294348.00 bytes/sec
total size is 3145728  speedup is 1.00

Confirm they were copied:

$ tree /home/saml/tmp/test/files
/home/saml/tmp/test/files
|-- folder1
|   `-- example.tar.gz
|-- folder2
|   `-- example.tar.gz
`-- folder3
    `-- example.tar.gz

tar

If you interested here's how you do it using just tar.

$ cd /home/saml/tmp
$ tar cvf - --files-from=<(head -n 3 /home/saml/tmp/abc.txt) | (cd /home/saml/tmp/test/files/; tar xvf -)
./folder1/example.tar.gz
./folder1/example.tar.gz
./folder2/example.tar.gz
./folder2/example.tar.gz
./folder3/example.tar.gz
./folder3/example.tar.gz

Confirm that it copied:

$ tree /home/saml/tmp/test/files
/home/saml/tmp/test/files
|-- folder1
|   `-- example.tar.gz
|-- folder2
|   `-- example.tar.gz
`-- folder3
    `-- example.tar.gz
  • but in my case i am using the head command to copy only a certain number of files, so my command is like $ rsync -avz head -n 100 /home/tmp/abc.txt /home/tmp/test/. /home/tmp/test/files This also copies only one example.tar.gz to the destination folder.what is wrong in this or how to use files-from in this command? – Mano Aug 17 '13 at 6:18
  • @user1752557 - you can use your head command as input to the --files-from= list. I'll add it to the answer. – slm Aug 17 '13 at 6:24
  • @user1752557 - see updates. – slm Aug 17 '13 at 6:40
  • Can you please tell me the version of linux which supports rsync – Mano Aug 20 '13 at 6:15
  • @user1752557 - any versions typically support it. It may not be installed but depending on the distros' package manager (apt, yum, etc.) it can be installed. – slm Aug 20 '13 at 6:26
0

The problem is most certainly not that cp doesn't copy directory structures. Of course it does: cp -r (recursive).

What cp, at least POSIX cp, doesn't do is re-create the relative paths of the source operands in the destination directory.

If you cp a/b/file1 a/b/file2 a/c/file3 dest then you get dest/file1 dest/file2 dest/file3.

If your cp is the one from GNU Coreutils, it may have the --parents option. Not sure when that was introduced. cp --parents will induce GNU cp into producing this path re-creation mechanism. From the Info documentation:

--parents
  Form the name of each destination file by appending to the target
  directory a slash and the specified name of the source file.  The
  last argument given to `cp' must be the name of an existing
  directory.  For example, the command:

      cp --parents a/b/c existing_dir

  copies the file `a/b/c' to `existing_dir/a/b/c', creating any
  missing intermediate directories.

So if you have GNU cp, the only change you need is to drop the -r since we are not recursing, and use --parents:

cp --parents -f `head -n 100 /home/tmp/abc.txt` /home/tmp/test/files

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.