You're iterating over the list of files twice, once in the grep & once in the foreach, and you don't need to do that. Also glob is easier to use than opendir/readdir, IMHO. So you could have done something like this
use v5.20;
use warnings;
use autodie qw/:all/;
use File::Glob qw/:bsd_glob/;
use File::Spec;
use File::Basename;
sub showtree {
my ($dir,$indent) = @_;
$indent .= ' ';
my @list = bsd_glob(File::Spec->catfile($dir,'*'));
foreach my $f (@list) {
if (-d $f) {
say $indent,'+-',basename($f);
showtree($f,$indent . '|');
}
if (-l $f) {
say $indent,'+-',basename($f),' --> ',readlink($f);
}
}
}
showtree($ARGV[0] // '.');