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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .