1

I use Ubuntu 20.04 and i have a lot of files under multiple subfolders under a parent folder. I need to copy only symlinks from within these subfolders to another folder maintaining the source folder structure. I need to retain them as it is with exactly same relative path information so that when they are in a new destination folder they still will continue to behave same as in source folder(destination folder has same folders/files as in source).

This is what I have:
Source/file1
Source/folder1/file2
Source/folder1/symlink1 -> ./file2
Source/folder2/symlink2 -> ../file1

This is what I need (symlinks will be ultimately moved to a folder where all files in source will be present in same folder structure)
Destination\folder1\symlink1 -> ./file2
Destination\folder2\symlink2 -> ../file1

Any help would be appreciated.

I have tried these below already

find ./ -type l | xargs -I % cp -va % Destination/
Result: all symlinks get copied to destination folder but they lose the source folder structure.

find . -type l | xargs -i cp {} Destination{}

Result: cp: cannot create regular file 'Destination./tools/i18n-uitext/node_modules/istanbul-lib-source-maps/node_modules/.bin/rimraf': No such file or directory

Here (below) are some of the symlinks i have in source folder.

Listed below symlinks using command find ./ -type l -print0 | xargs -0 ls -plah from within the source directory. I am intending to copy these symlinks to another directory where they need to maintain this same folder structure.


Note: The source directory is a CI machines workspace folder on one server and the destination directory is a folder outside this workspace folder where i need to copy these symlinks and folders containing them into.

lrwxrwxrwx 1   19 Jul  4 18:08 ./integrations/link_adyen_v20_1_3/node_modules/.bin/_mocha -> ../mocha/bin/_mocha
lrwxrwxrwx 1   18 Jul  4 18:08 ./integrations/link_adyen_v20_1_3/node_modules/.bin/acorn -> ../acorn/bin/acorn
lrwxrwxrwx 1   19 Jul  4 18:08 ./integrations/link_adyen_v20_1_3/node_modules/.bin/atob -> ../atob/bin/atob.js

lrwxrwxrwx 1   19 Jul  4 18:05 ./node_modules/.bin/_mocha -> ../mocha/bin/_mocha
lrwxrwxrwx 1   18 Jul  4 18:05 ./node_modules/.bin/acorn -> ../acorn/bin/acorn
lrwxrwxrwx 1   19 Jul  4 18:05 ./node_modules/.bin/atob -> ../atob/bin/atob.js
lrwxrwxrwx 1   32 Jul  4 18:05 ./node_modules/.bin/autoprefixer -> ../autoprefixer/bin/autoprefixer

lrwxrwxrwx 1   20 Jul  4 18:05 ./node_modules/@babel/compat-data/node_modules/.bin/semver -> ../semver/bin/semver
lrwxrwxrwx 1   20 Jul  4 18:05 ./node_modules/@babel/core/node_modules/.bin/semver -> ../semver/bin/semver

lrwxrwxrwx 1   22 Jul  4 18:05 ./node_modules/caniuse-api/node_modules/.bin/browserslist -> ../browserslist/cli.js
lrwxrwxrwx 1   23 Jul  4 18:05 ./node_modules/core-js-compat/node_modules/.bin/semver -> ../semver/bin/semver.js

lrwxrwxrwx 1   20 Jul  4 18:08 ./tools/i18n-uitext/node_modules/.bin/semver -> ../semver/bin/semver
lrwxrwxrwx 1   21 Jul  4 18:08 ./tools/i18n-uitext/node_modules/.bin/uuid -> ../uuid/dist/bin/uuid
lrwxrwxrwx 1   18 Jul  4 18:08 ./tools/i18n-uitext/node_modules/.bin/which -> ../which/bin/which
lrwxrwxrwx 1   20 Jul  4 18:08 ./tools/i18n-uitext/node_modules/fstream/node_modules/.bin/mkdirp -> ../mkdirp/bin/cmd.js
lrwxrwxrwx 1   16 Jul  4 18:08 ./tools/i18n-uitext/node_modules/fstream/node_modules/.bin/rimraf -> ../rimraf/bin.js
1
  • @KamilMaciorowski Thank you again :-) Apologies it took me so long to explain clearly. I have updated the description with this information so that it helps anyone.
    – Ajith John
    Jul 14 at 11:58

1 Answer 1

0
  1. Go to the Source directory:

    cd /path/to/Source
    
  2. Pipe find . -type l to tar --files-from=-. I can see your find supports -print0, use it:

    find . -type l -print0 | tar -c --null --files-from=- -f symlinks.tar
    
  3. Copy or move symlinks.tar to the Destination directory. cd to the directory.

  4. Extract there:

     tar -xf symlinks.tar
    

This will work even if Source and Destination are on two different machines, if only you can copy the file from one machine to the other.

If Source and Destination both belong to the directory hierarchy on a single machine then you don't need any intermediate regular file. Pipe one tar to another:

( cd /path/to/Source && find . -type l -print0 | tar -c --null --files-from=- ) \
| ( cd /path/to/Destination && tar -x )

Notes:

  • cd … && foo … will run foo only if cd succeeds. This is the right thing to do.

  • In general our tar -x does not need directory structure to exist beforehand; it will create directories to put symlinks into, if needed. But don't expect these newly created directories to receive properties (e.g. mode) from subdirectories in Source. The reason is our tar -c stores no information about directiories. It stores information about symlinks only, because our find finds nothing but symlinks. The path to a symlink (received from find) may contain directory components and tar -x will use this information to create subdirectiories if needed, but this is it. No information about any directory per se is available.

1
  • Thank you, that saved my day :-D The above suggestion worked like a magic. Really appreciate you spending time to understand the issue very clearly and then solving it.
    – Ajith John
    Jul 15 at 7:50

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.