2

I want to create symlinks to all files in 'myfiles' which are not already linked to and specify the destination folder for the just-created symlinks.

I am using the following cmd, successfully, to generate the list of existing links, which point to 'myfolder' :

find ~/my-existing-links/ -lname '*/myfiles/*' -printf "%f\n" > results.txt

And I'm using the following cmd to reverse match i.e. to list the files in myfiles which are not linked to:

ls ~/myfiles | grep -vf results.txt > results2.txt

So, results2.txt has a list of the files, each of which I now want to create a new symlink to.... in a folder called ~/newlinks .

I know it is possible to feed 'ln -s' a file list using the find / exec combination i.e.

find ~/myfiles/ -exec ln -s {} -t ~/newlinks \; -print

.... but that would be the unfiltered file list in myfiles. I want to use the filtered list.

Any ideas how I can do this? I'm going to be adding files to myfiles regularly and so will periodically visit the folder for the purpose of generating symlinks for all the new files so I can divi the links up logically(rather than change the original filename).

Jim
  • 201
  • 3
  • 10

4 Answers4

4

Try with xargs:

cat results2.txt | xargs -I{} ln -s {} ~/newlinks
pasaba por aqui
  • 3,446
  • 16
  • 40
2

You can use xargs to apply the links, so that your composite command might look like this:

find ~/myfiles/ | grep -vf results.txt | xargs make-my-links

and make-my-links would be a script something like this:

#!/bin/sh
for source in "$@"
do
    ln -s "$source" -t ~/newlinks
done

The separate script and loop are used with xargs because it does not accept a command-template, but will (default) send as many of the inputs as it thinks will fit on a command-line.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
1

So, you have 3 entities of type directory:

  • ~/myfiles/: contains your files.
  • ~/my-existing-links/: contains links to files from ~/myfiles/.
  • ~/newlinks/: contains links to new files from ~/myfiles/

To me, the third entity is rather unnecessary. Why the new links aren't created directly in ~/my-existing-links/?

I would only use a script to update the list of links in ~/my-existing-links/, whenever new files are added in ~/myfiles/:

update_v1.sh

#!/bin/bash
for f in $(find ~/myfiles -type f); do
    ln -sf "$f" "~/my-existing-links/$(basename $f)"
done

update_v2.sh

find ~/myfiles -type f -exec sh -c \
     'for f; do ln -sf "$f" "~/my-existing-links/${f#*/}"; done' sh {} +

update_print.sh

#!/bin/bash
for f in $(find ~/myfiles -type f); do
    if [[ ! -L "~/my-existing-links/${f#*/}" ]]; then
        echo "Link not existing for $f"
    fi
done
Eugeniu Rosca
  • 5,177
  • 16
  • 45
  • 1
    Instead of checking if exists prior to creation, `ln -sf` to force creation of link despite exists or not. – Cometsong Jun 07 '15 at 18:05
  • Thanks chatraed. Haven't tried it but looks succinct. The reason I choose to file new links in a separate folder is that I want to manually eye-ball them before I file them in an appropriate folder under a main 'links' folder and/or rename and/or copy the link as I file. But anyway, thanks for your input. – Jim Jun 08 '15 at 08:15
  • @Jim: I still believe the task of "eye-balling" the new files could be accomplished without a 3rd directory `~/newlinks/`. I've added the `update_print.sh` example, to print those files that have no link pointing to them from `~/my-existing-links`. – Eugeniu Rosca Jun 08 '15 at 08:38
0

Thanks, Thomas and pasaba... I found a way to do it:

So I did the following from ~/newlinks :

while read line; do ln -s "$line" "${line##*/}" ; done < ~/myfiles/results2.txt

Thanks again for your time.

Community
  • 1
  • 1
Jim
  • 201
  • 3
  • 10