7

I want to check if a directory exists and it has access rights; if it does, then perform the tasks. This is the code I wrote, which might not have proper syntax.

Can you help me to correct it?

dir_test=/data/abc/xyz
if (test -d $dir_test & test –x $dir_test -eq 0);
 then
cd $dir_test
fi

I believe this can also be written like this.

dir_test=/data/abc/xyz
test -d $dir_test
if [ $? -eq 0 ];
then
test –x $dir_test
if [ $? -eq 0 ];
then
cd $dir_test
fi
fi

How can we write this more efficiently?

apaderno
  • 28,547
  • 16
  • 75
  • 90
Rahul sawant
  • 415
  • 3
  • 6
  • 13
  • Because `[` ... `]` is a synonym for `test` this classifies as a **useless use of `test`** ;-) See @chepner for the explanation. – Henk Langeveld Mar 25 '14 at 07:21
  • More examples and explanation here: [How to check if a directory exists in a shell script](http://stackoverflow.com/questions/59838/how-to-check-if-a-directory-exists-in-a-shell-script) – Henk Langeveld Mar 25 '14 at 07:23

3 Answers3

19

The best way to write the original test-based solution would be

if test -d "$dir_test" && test –x "$dir_test";
then
    cd $dir_test
fi

although what will you do if the test fails and you don't change directories? The remainder of the script will probably not work as expected.

You can shorten this by using the [ synonym for test:

if [ -d "$dir_test" ] && [ -x "$dir_test" ]; then

or you can use the conditional command provided by bash:

if [[ -d "$dir_test" && -x "$dir_test" ]]; then

The best solution, since you are going to change directories if the tests succeed, is to simply try it, and abort if it fails:

cd "$dir_test" || {
  # Take the appropriate action; one option is to just exit with
  # an error.
  exit 1
}
chepner
  • 497,756
  • 71
  • 530
  • 681
1
dir_test=/data/abc/xyz
if (test -d $dir_test & test –x $dir_test -eq 0); # This is wrong. The `-eq 0` part will result in `test: too many arguments`. The subshell (parens) is also unnecessary and expensive.
 then
cd $dir_test
fi

cd can tell you if a directory is accessible. Just do

cd "$dir_test" || exit 1;

Even if you do decide to use test first, for some reason, you should still check the exit status of cd, lest you have a race condition.

chepner
  • 497,756
  • 71
  • 530
  • 681
kojiro
  • 74,557
  • 19
  • 143
  • 201
0
if [ -d $dir_test -a -x $dir_test ]

alternatively if you have /usr/bin/cd:

if [ /usr/bin/cd $dir_test ]
Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 1
    The POSIX standard recommends `[ -d $dir_test ] && [ -x $dir_test ]` in place of the `-a` operator. – chepner Mar 24 '14 at 15:45