Using Bash, how do I feed a file list into a 'ln -s' without using 'find'?

1.5k views Asked by At

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).

4

There are 4 answers

0
pasaba por aqui On

Try with xargs:

cat results2.txt | xargs -I{} ln -s {} ~/newlinks
0
Thomas Dickey On

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.

3
Eugeniu Rosca On

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
0
Jim On

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.