I want to make a bash script that symlink files for me instead of doing this manually. In my mind the workflow would be something like this :

Question 1 : What is the path of the file/folder to be the source ? ( user input the source )

Question 2 : What is the path of the destination ? ( user input destination )

And then I would take this input and make it variable $SOURCE and $DESTINATION

Then I would just run something like :

mkdir -p $DESTINATION 

The script should forget the variables after every run, and also run in loop until user decides to quit it.

Also if a user input a destination that ends with a different filename as is often desired, how I can mkdir the directory but exclude the file name?

Like /root/files/1 and I want to symlink it to /var/files/2. Being "2" just a different name for file "1". How can I make my script that smart?

Sorry if this is a stupid question, I'm just new to this world and this script is going to be one of the most complex I ever wrote.

  • You are asking several questions, which are technically unrelated (related only by the fact that you happen to need the answer for the same program): How to ask the user for input, how to write a loop based on a certain condition, and how to exclude a file name from a path (3 questions). In this case you should create three threads in this forum, one for each question. Also, I can't help wondering to what extend you were reading the bash man-page before asking this. Also, for the question of reading user input, you can use this well known website. Sep 11, 2017 at 6:50
  • For the mkdir part, see if dirname is what you are looking for: dirname path/to/entry.a.b.c returns path/to.
    – njsg
    Sep 11, 2017 at 9:03

1 Answer 1


It seems that you want something like this:

#!/usr/bin/env bash

while :; do

  read -r -p 'Source: ' source
  read -r -p 'Destination: ' destination

  [[ $destination != */* ]] || mkdir -p -- "${destination%/*}" &&
    ln -s -- "${source}" "${destination}"

  read -r -p 'Exit? (type "e" to exit): '
  [[ "${REPLY}" == 'e' ]] && break



$ cd ~/Desktop
$ ls -l
total 0
$ touch file
$ ls -l
total 0
-rw-rw-r-- 1 a a 0 sep 11 03:13 file
$ my_script.sh
Source: ./file
Destination: ./dir/file_copy_1
Exit? (type "e" to exit): 
Source: ./file
Destination: ./dir/file_copy_2
Exit? (type "e" to exit): e
$ ls -l ./dir
total 2
lrwxrwxrwx 1 a a 6 sep 11 03:15 file_copy_1 -> ./file
lrwxrwxrwx 1 a a 6 sep 11 03:15 file_copy_2 -> ./file

I couldn't completely understand your question about mkdiring the directory excluding the filename (sorry, I'm not a native english speaker), so I just improvised that part, but if you give me more examples about what you exactly want maybe I could help you.

  • This gets messed up if you give the destination without a directory, i.e. as a plain filename. This is however not your fault. The question does not specify what to do in that case.
    – Kusalananda
    Sep 11, 2017 at 8:33
  • @Kusalananda Thanks for the feedback. I think it could be avoided by adding grep -F -e '/' <<< "${destination}" > '/dev/null' 2>&1 || destination="./${destination}" before the mkdir part in my original answer. Although now that I see the edition of Stéphane I guess his approach is better and cleaner.
    – nxnev
    Sep 11, 2017 at 8:56

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.