I would like to make an exact copy of a directory (which contains sub-directories, files, and symlinks) except that I want each file in the target directory to be a symlink back to the original file.

This I can already accomplish using:

cp -sR /home/me/SourceDir TargetDir

However, I would like any relative symlinks within SourceDir that point to somewhere else in SourceDir to remain the same relative links, hence now pointing to TargetDir.

For example, let's say SourceDir contains the following:

File0
Dir1/File1
Dir1/File2
Dir2/File3
Dir2/File2   <-- this is a symlink to ../Dir1/File2

Then I would like TargetDir to look like:

File0        <-- symlink to  ../SourceDir/File0
Dir1/File1   <-- symlink to  ../../SourceDir/Dir1/File1
Dir1/File2   <-- symlink to  ../../SourceDir/Dir1/File2
Dir2/File3   <-- symlink to  ../../SourceDir/Dir2/File3
Dir2/File2   <-- this is still a symlink to ../Dir1/File2, so: TargetDir/Dir1/File2

I wouldn't mind if this had to be accomplished in two or three steps (something I could write into a simple shell script).

One thought I had was first copying all symlinks only, then doing the cp -sR with a no-clobber.

  • Sorry, but this makes me so curious: why? – Arjan Oct 25 '15 at 21:40
  • 1
    I'm curious, too, why you want to do this. It would seem that a symlink to the directory itself would suffice. – Ron Maupin Oct 25 '15 at 21:43
  • Arjan, how I have shown it in the example is how I would like it to be. In other words, in TargetDir, the Dir2/File2 is a link pointing to the other File2 within TargetDir, specifically to TargetDir/Dir1/File2. – Madeleine P. Vincent Oct 25 '15 at 23:09
  • 1
    Arjan, Ron, The reason for this is more complicated than my example lets on. Eventually, some files in TargetDir will be altered and other files will be created/added/deleted, and thus a simple symlink to the original directory itself will not suffice. – Madeleine P. Vincent Oct 25 '15 at 23:12
up vote 2 down vote accepted

You haven't said you are in /home/me, but your cp command will create all your links as absolute, wherever you are, ie TargetDir/File0 -> /home/me/SourceDir/File0 etc, not the relative links you illustrate.

You can achieve what you want using find:-

cp -sR /home/me/SourceDir TargetDir
cd /home/me/SourceDir
find -type l -exec cp -P "{}" "/Path/To/TargetDir/{}" \;
  • The first command is your original.
  • By positioning yourself in the source directory you eliminate it from the find path.
  • The find with cp -P overwrites the links with verbatim copies of the source links.
  • The double-quotes allow for files and directories with embedded blanks.

If you really want relative links (TargetDir/File0 -> ../../SourceDir/File0 etc) for your normal files, you will need to use find -type f and execute mkdir -p to create the target directory structure, then find -type f and execute ls -s for each file.

  • Nice note on the cp command; I didn't even think about that. – Arjan Oct 26 '15 at 6:52
  • 1
    Perfect solution! I also use the symlinks command to clean up links and make them relative. From the TargetDir/ just execute: symlinks -csr ./ – Madeleine P. Vincent Oct 26 '15 at 12:00
  • Thanks for mentioning symlinks: I've not met it before, and it looks rather useful. – AFH Oct 26 '15 at 13:09

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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