Creating symbolic link recursively

24,035

Solution 1

You'll probably want to use the find command using the maxdepth option. I created this sample directory structure:

/tmp/parent
/tmp/parent/subdir2
/tmp/parent/subdir1
/tmp/parent/subdir4
/tmp/parent/subdir4/notme
/tmp/parent/subdir3

Let's say I wanted to create a symlink to /tmp/hooks in each subdir but not the notme subdir:

root@xxxxxxvlp12 ~ $ find /tmp/parent -type d -maxdepth 1 -exec ln -s /tmp/hooks {} \;
root@xxxxxxvlp12 ~ $ find /tmp/parent -ls
2490378    4 drwxr-xr-x   6 root     root         4096 Oct  7 12:39 /tmp/parent
2490382    4 drwxr-xr-x   2 root     root         4096 Oct  7 12:39 /tmp/parent/subdir2
2490394    0 lrwxrwxrwx   1 root     root           10 Oct  7 12:39 /tmp/parent/subdir2/hooks -> /tmp/hooks
2490379    4 drwxr-xr-x   2 root     root         4096 Oct  7 12:39 /tmp/parent/subdir1
2490395    0 lrwxrwxrwx   1 root     root           10 Oct  7 12:39 /tmp/parent/subdir1/hooks -> /tmp/hooks
2490389    4 drwxr-xr-x   3 root     root         4096 Oct  7 12:39 /tmp/parent/subdir4
2490390    4 drwxr-xr-x   2 root     root         4096 Oct  7 12:38 /tmp/parent/subdir4/notme
2490396    0 lrwxrwxrwx   1 root     root           10 Oct  7 12:39 /tmp/parent/subdir4/hooks -> /tmp/hooks
2490387    4 drwxr-xr-x   2 root     root         4096 Oct  7 12:39 /tmp/parent/subdir3
2490397    0 lrwxrwxrwx   1 root     root           10 Oct  7 12:39 /tmp/parent/subdir3/hooks -> /tmp/hooks
2490391    0 lrwxrwxrwx   1 root     root           10 Oct  7 12:39 /tmp/parent/hooks -> /tmp/hooks

Solution 2

find can be used to execute a command in the context of every directory under a specific path.

The following command looks for all files under /var/opt/gitlab/git-data/repositories/web/ that are directories (-type d) and creates a symbolic link relative to the current directory it is examining (represented by {} in -exec )

So the following find command will do what you require:

find /var/opt/gitlab/git-data/repositories/web/ -type d -exec ln /opt/gitlab/embedded/service/gitlab-shell/hooks/ {}/hooks \;

Solution 3

After looking around and playing with the find command I found it was easier to just loop over things using ./*/. Thanks for all the help! I made a script on my github account that is much more finely tuned. Although it is gitlab specific It would only take a few minutes to modify it for whatever you need https://github.com/michaeljs1990/bash-scripts/blob/master/gitlab-hooks-migration.sh.

#!/bin/bash

find . -name "hooks" -type l -delete

hooks="hooks"
for i in ./*/; do
    ln -s  /opt/gitlab/embedded/service/gitlab-shell/hooks/ $i$hooks
done

Solution 4

ln works a bit like cp. If there are more than two arguments, the last one is treated as a directory.

From man ln:

ln [option]... target... directory

You'll need to use a for loop instead.

Share:
24,035

Related videos on Youtube

eatingthenight
Author by

eatingthenight

Updated on September 18, 2022

Comments

  • eatingthenight
    eatingthenight almost 2 years

    I essentially want to run this command...

    ln -s /opt/gitlab/embedded/service/gitlab-shell/hooks/ /var/opt/gitlab/git-data/repositories/web/*/hooks
    

    This would create a symbolic link in all folders under the web folder called hooks however it returns no errors but it does not actually add the symlink.