1

I created the following code:

#!/bin/bash

rdir="~/bin/Test/"
echo $rdir
echo $rdir"folderA"
/bin/mkdir -p $rdir"folderA"

# files is an array. () is used to enclose array elements and 
#       each array element enclosed by "".  
files=(
"Apple"
"Apple\ Pie")

IFS="" # What is this for?

for f in ${files[@]}
do
   echo "$rdir${f}"
   /bin/touch "$rdir${f}"
   /bin/ln -s "$rdir${f}" "$rdir${f}"_linktarget"   
   /bin/ln -s "$rdir${f}" "$rdirfolderA"${f}"_linktarget"   

done

I call this code test2.sh and get the below results after executing it:

$ ./test2.sh 
~/bin/Test/
~/bin/Test/folderA
./test2.sh: line 22: unexpected EOF while looking for matching `"'
./test2.sh: line 25: syntax error: unexpected end of file
$ ls -a
~  .  ..  test2.sh

Problems:

  • The mkdir -p command did not create the folder.
  • The touch command could not create files named according to the array elements. One of the array element contains two words with a space between them. I created the for loop to handle such array elements following the answer of Khushneet.
  • I could not create soft link of the touch files and its target in the current directory or the sub-directory "folderA".

Questions:

  • How to solve these 3 problems.

  • What is IFS and how to use it?

Thanks.

4
  • 3
    the mkdir/ln -s code is not executing because of the error message you're getting which indicates a syntax error when the script runs. Run you code thru shellcheck.net and fix those issues first, That may solve it. If not update your Q with current code and error msgs. Good luck.
    – shellter
    Commented May 7, 2016 at 1:43
  • If you look at the code highlighting in the question you can see the line with 3 double quotes on it which is wreaking havoc. Commented May 7, 2016 at 2:45
  • @ shelter thanks for introducing shellcheck.net
    – Sun Bear
    Commented May 8, 2016 at 12:57
  • @JonathanLeffler. Thanks for pointing out my typo.
    – Sun Bear
    Commented May 8, 2016 at 12:58

4 Answers 4

1

These would be your final script (based on Shellcheck).

#!/bin/bash

rdir="$HOME/bin/Test/"  
# The original statment was  rdir="~/bin/Test/"
# You  need to use $HOME, as ~ doesn't expand inside double quotes
echo "$rdir" #enclosed the whole variable in double quotes
rdirfolderA="$rdir"/folderA #added this line
/bin/mkdir -p "$rdirfolderA" 
#ihave put $rdir inside quotes to prevent word splitting and globbing

# files is an array. () is used to enclose array elements and 
#       each array element enclosed by "".  
files=(
"Apple"
"Apple\ Pie")
#It is recommended to store the old IFS like this
IFS_old="$IFS"
IFS="" # What is this for? Sets the field separator to null
#you need this because you don't have a separating character between the
#strings in the array

for f in "${files[@]}"   #Double quote array expansions to avoid re-splitting elements.
do
   echo "$rdir${f}" 
   /bin/touch "$rdir${f}"
   /bin/ln -s "$rdir${f}" "$rdir${f}"_linktarget   # Removed the  additional double-quote at the end.
   /bin/ln -s "$rdir${f}" "$rdirfolderA/${f}"_linktarget   
done
#Restore the old IFS
IFS="$IFS_old"
#Do something else with your script.
1
  • Thanks for the explanations in the revised codes. Will use $HOME instead of ~. Your code works on my bash version. Pls note one the backslash typically used in command line to handle space in file names such as in "Apple\ Pie" is redundant, i.e. "Apple Pie" is sufficient.
    – Sun Bear
    Commented May 8, 2016 at 13:10
1

Few syntax errors I can spot .. (hope this helps)

/bin/mkdir -p $rdir"folderA"

--> Change to /bin/mkdir -p "${rdir}folderA"

... Then the following sym-links, a similar change again

/bin/ln -s "$rdir${f}" "$rdir${f}"_linktarget"   
/bin/ln -s "$rdir${f}" "$rdirfolderA"${f}"_linktarget"

--> Change to:

/bin/ln -s "${rdir}${f}" "${rdir}${f}_linktarget"   
/bin/ln -s "${rdir}${f}" "${rdir}folderA${f}_linktarget" 

... Essentially there is a slight difference between $var and ${var}, esp. when used in string-concatenation.

1
#!/bin/bash

rdir="~/bin/Test/"
echo $rdir
echo $rdir"folderA"
/bin/mkdir -p ${rdir}"folderA"

# files is an array. () is used to enclose array elements and
#       each array element enclosed by "".
files=(
"Apple"
"Apple\ Pie"
"Mango")

IFS="" # What is this for?

for f in ${files[@]}
do
   echo "${rdir}${f}"
   /bin/touch "${rdir}${f}"
   /bin/ln -s $rdir${f} $rdir${f}"_linktarget"
   /bin/ln -s ${rdir}${f} ${rdirfolderA}${f}"_linktarget"

done

Result:

lrwxrwxrwx  1 monk monk      16 May  7 00:33 Apple_linktarget -> ~/bin/Test/Apple
lrwxrwxrwx  1 monk monk      21 May  7 00:33 Apple\ Pie_linktarget -> ~/bin/Test/Apple\ Pie
lrwxrwxrwx  1 monk monk      16 May  7 00:33 Mango_linktarget -> ~/bin/Test/Mango
1
  • Thanks monk for your quick reply. Note the link between files in folderA and rdir did not materialise. Also a mistake on my part was using ~ instead of $HOME as pointed out by @sjsam below. I have found the answer and will post what works on my bash version below.
    – Sun Bear
    Commented May 8, 2016 at 12:54
0

The Working Script:

#!/bin/bash

rdir=$HOME"/bin/Test/"
echo $rdir
echo $rdir"folderA"
/bin/mkdir -p $rdir"folderA"

# files is an array. () is used to enclose array elements and 
#       each array element enclosed by "".  
files=(
"Apple"
"Apple Pie")

IFS="" 

for f in ${files[@]}
do
   echo $rdir${f}
   /bin/touch $rdir${f}
   /bin/ln -s $rdir${f} $rdir${f}"_linktarget"   
   /bin/ln -s $rdir${f} $rdir"folderA/"${f}"_linktarget"   

done

Answers:

  1. It was wrong to say mkdir -p $rdir"folderA" command did not create the folder "folderA". The folder was created as $HOME/bin/Test/~/bin/Test/folderA. However, this was not the intent. It was needed as $HOME/bin/Test/folderA. The mistake arouse because as pointed out by @sjsam "~ doesn't expand inside double quotes" and variable $HOME should have been used to indicate home directory.
  2. Problem 2 & 3 occurred because of typo on " as mentioned by @shelter, @Jonathan Leffler and @sjsam, and the overzealous use of "". By limiting the use of "" to string instead of using it to enclose $variable and ${array} was sufficient to get the script to work.
  3. The backslash \ typically used in command line to handle space in file names such as in "Apple\ Pie" was redundant, i.e. "Apple Pie" is sufficient as IFS="" was used.

Version of Bash used to execute the script:

$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

I like to thanks all answer contributors for their quick responses. :)

Not the answer you're looking for? Browse other questions tagged or ask your own question.