Search code examples
bashln

Create symbolic links for multiple books collected from command `find`


I'd like to create links of books.

Firstly, I collect all the JS books

    find ~ -type f -iregex -Eo '.*javascript.*\.pdf' > js_books.md 2>/dev/null

It returns 35 books

    ../Coding/Books/HTML_Collections/Freeman E.T., Robson E. - Head First HTML5. Programming Building Web Apps with JavaScript - 2011.pdf
    ../Coding/Books/HTML_Collections/Learning Web Design - A Beginner's Guide to HTML, CSS, JavaScript, and Web Graphics - Jennifer Niederst Robbins - 4th Edition - August 2012.pdf
    ..

Additionally to copy them to directory js_books

    mkdir js_books
    find ~ -type f -iregex -Eo '.*javascript.*\.pdf' print0 -exec cp '{}' js_books

It works, however, multiple copies consume lots of disk space.
So I delete the books and try to make symbolic link within.

    find ~ -type f -iregex  '.*javascript.*\.pdf' -print0 -exec ln -s '{}' js_books/'{}' \;

It returns nothing in dir js_books.

How to work out such a problem?


Solution

  • Sorry again. I don't have access to BSD ln at the moment, but I would assume that '{}' contains the full path, and doing '{}' js_books/'{}' should get you something like /home/.../file js_books//home/.../file, which is of course nonsense.

    In my version of ln, I don't even need to specify the -t option, i.e., the following command works:

    find ~ -type f -name "*.pdf" -exec ln -s {} js_books \;
    

    If this doesn't work for you, try using basename to get the file name without the path:

    find ~ -type f -name "*.pdf" -exec sh -c 'ln -s "{}" "temp/$(basename "{}")"' \;
    

    Sorry. Previous answer didn't work so well. Instead, try using full paths for both source and destination.


    For reference, the previous answer was:

    Use ln's -t option:

    -t, --target-directory=DIRECTORY specify the DIRECTORY in which to create the links

    So your command becomes find ~ -type f -iregex '.*javascript.*\.pdf' -print0 -exec ln -s -t js_books/ '{}' \;