I can check, if a file exists and is a symbolic link with -L

for file in *; do
    if [[ -L "$file" ]]; then echo "$file is a symlink"; else echo "$file is not a symlink"; fi

and if it is a directory with -d:

for file in *; do
    if [[ -d "$file" ]]; then echo "$file is a directory"; else echo "$file is a regular file"; fi

But how can I test for only links to directories?

I simulated all cases in a test folder:

/tmp/test# ls
a  b  c/  d@  e@  f@

/tmp/test# file *
a: ASCII text
b: ASCII text
c: directory
d: symbolic link to `c'
e: symbolic link to `a'
f: broken symbolic link to `nofile'

3 Answers 3


Just combine the two tests with &&:

if [[ -L "$file" && -d "$file" ]]
    echo "$file is a symlink to a directory"

Or, for POSIX compliant-syntax, use:

if [ -L "$file" ] && [ -d "$file" ]

Note: the first syntax using [[ expr1 && expr2 ]] is valid, but only works in certain shells such as ksh (where it comes from), bash or zsh. The second syntax using [ expr1 ] && [ expr2 ] is POSIX-compliant and even Bourne-compatible, meaning it will work in all modern sh and sh-like shells

  • 1
    If you want to check hidden files and directories too preceed this before: shopt -s dotglob
    – rubo77
    May 29, 2014 at 16:04

Here is a single command which will recursively list symlinks whose target is a directory (starting in the current directory):

find . -type l -xtype d

Reference: http://www.commandlinefu.com/commands/view/6105/find-all-symlinks-that-link-to-directories


A solution with find and using a function:

dosomething () {
    echo "doing something with $1"; 
find -L -path './*' -prune -type d| while read file; do 
    if [[ -L "$file" && -d "$file" ]];
        then dosomething "$file";
  • 1
    Using find and a while read for that is kinda overkill... Aug 20, 2014 at 14:20
  • 2
    Find is really useful if you search only for certain files
    – rubo77
    Aug 21, 2014 at 12:40

You must log in to answer this question.

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