HELP on checking for directory or symbolic link

Hi,

Can anyone please advise why the following is not working as I expected it to be?

Test script as below:

#!/bin/ksh

for checkdir in dir*
do
   echo "Checking ${checkdir}"

   if [ -d "${checkdir}" ] ; then
      echo "... ${checkdir} is a directory"
   elif [ -h "${checkdir}" ; then
      echo "... ${checkdir} is a symbolic link"
   fi
done

Output from sample run as below:

$: ./x.ksh

Checking dir1
... dir1 is a directory
Checking dir2
... dir2 is a directory
Checking dir3
... dir3 is a directory

Directory listing as below:

$: ls -l
total 24
drwxr-x--x   2 oracle   dba         4096 Aug 31 23:42 dir1
drwxr-x--x   2 oracle   dba         4096 Aug 31 23:42 dir2
lrwxrwxrwx   1 oracle   dba            4 Aug 31 23:43 dir3 -> /tmp
-rwxr-----   1 oracle   dba          239 Aug 31 23:45 x.ksh

Am kinda hoping that it will report dir3 as a symbolic link. At the moment, only workaround I can think of is to do ls -l ${checkdir} | grep "^l" and if it is non-zero then it is a symbolic link, otherwise it is not. Is this the solution?

I've also tried doing -L instead of -h and it gives the same result.

Feedback and advise much appreciated. Thanks in advance.

You could just test for a link first.

You have missed ] in the code....:slight_smile:

Hi pamu,

Just tried and got the same result.

/tmp$: cat x.ksh
#!/bin/ksh

for checkdir in dir*
do
   echo "Checking ${checkdir}"

   if [[ -d "${checkdir}" ]] ; then
      echo "... ${checkdir} is a directory"
   elif [[ -h "${checkdir}" ]] ; then
      echo "... ${checkdir} is a symbolic link"
   fi
done
/tmp$: ls -ltrd dir*
drwxr-x--x   2 oracle   dba         4096 Aug 31 23:42 dir1
drwxr-x--x   2 oracle   dba         4096 Aug 31 23:42 dir2
lrwxrwxrwx   1 oracle   dba            4 Aug 31 23:43 dir3 -> /tmp
/tmp$: ./x.ksh
Checking dir1
... dir1 is a directory
Checking dir2
... dir2 is a directory
Checking dir3
... dir3 is a directory
/tmp$:

Also tried CarloM's suggestion and same problem.

---------- Post updated at 04:38 PM ---------- Previous update was at 04:27 PM ----------

Hi CarloM,

Tried your suggestion, unfortunately, now it goes like below:

tmp $: ls -ltrd dir*
drwxr-x--x   2 oracle   dba         4096 Aug 31 23:42 dir1
drwxr-x--x   2 oracle   dba         4096 Aug 31 23:42 dir2
lrwxrwxrwx   1 oracle   dba            4 Aug 31 23:43 dir3 -> /tmp
tmp $: cat y.ksh
#!/bin/ksh

for checkdir in dir*
do
   echo "Checking ${checkdir}"

   if [[ -h "${checkdir}" ]] ; then
      echo "... ${checkdir} is a directory"
   elif [[ -d "${checkdir}" ]] ; then
      echo "... ${checkdir} is a symbolic link"
   fi
done
tmp $: cat z.ksh
#!/bin/ksh

for checkdir in dir*
do
   echo "Checking ${checkdir}"

   if [[ -L "${checkdir}" ]] ; then
      echo "... ${checkdir} is a directory"
   elif [[ -d "${checkdir}" ]] ; then
      echo "... ${checkdir} is a symbolic link"
   fi
done
tmp $: ./y.ksh
Checking dir1
... dir1 is a symbolic link
Checking dir2
... dir2 is a symbolic link
Checking dir3
... dir3 is a directory
tmp $: ./z.ksh
Checking dir1
... dir1 is a symbolic link
Checking dir2
... dir2 is a symbolic link
Checking dir3
... dir3 is a directory
tmp $:

Nearly there but the echo statements do not match the tests. The Conditional Expression syntax "[[ .....]]" is not needed.

#!/bin/ksh

for checkdir in dir*
do
   echo "Checking ${checkdir}"

   if [ -h "${checkdir}" ] ; then
      echo "... ${checkdir} is a symbolic link"
   elif [ -d "${checkdir}" ] ; then
      echo "... ${checkdir} is a directory"
   fi
done
1 Like

Agreed, but it is useful. With it you do not have to explicitly quote the checkdir variable as quotes are implicitly added.

if [[ -h ${checkdir} ]] ; then
      echo "... ${checkdir} is a symbolic link"
elif [[ -d ${checkdir} ]] ; then
      echo "... ${checkdir} is a directory"
fi              

Thanks a lot methyl, that is so very embarrassing :wall::o ....

All good now ... still stumped on why the -d returns true for a symbolic link though, it's like it is trying to check whether the link that the symlink is set to is a directory.

I can live with doing the -h then the -d for the time being ... thanks again for pointing out my mistakes ... need to grab some more coffee I guess

Below is an example where I create another symbolic link but the actual directory /tmp/x does not exist and my original script works like how I want it to. Any chance that there is a test where it will not try and resolve what the symbolic link is linking to?

tmp $: ./x.ksh
Checking dir1
... dir1 is a directory
Checking dir2
... dir2 is a directory
Checking dir3
... dir3 is a directory
Checking dir4
... dir4 is a symbolic link
tmp $: cat x.ksh
#!/bin/ksh

for checkdir in dir*
do
   echo "Checking ${checkdir}"

   if [[ -d "${checkdir}" ]] ; then
      echo "... ${checkdir} is a directory"
   elif [[ -h "${checkdir}" ]] ; then
      echo "... ${checkdir} is a symbolic link"
   fi
done
tmp $: ls -ltrd /tmp
drwxrwxrwt  79 root     root      221472 Sep  1 12:41 /tmp
tmp $: ls -ltrd /tmp/x
/tmp/x: No such file or directory
tmp $:

Check the highlighted part.......:slight_smile:

None that I can think of which use test .

There is a complex method with find ! -follow .

This is a generic answer.
We don't know what Operating System and version you have or what version of Korn Shell you are running.
Even having test -h rather than test -L syntax suggests that this is not mainstream unix.