简体   繁体   中英

bash: && operator behaviour

I am practicing bash scripting and have a question about && operator

As per O'reily bash cookbook if the command before && operator fails the command that precedes it should cease to execute

See below code

-bash-4.2$ pwd
/home/postgres
-bash-4.2$ mkdir testdir
-bash-4.2$ dir=testdir1
-bash-4.2$ cd $dir1 && rm -rf *
-bash-4.2$ echo $?
0
-bash-4.2$ ls

I expect the rm -rf command to fail as the command cd testdir1 fails, but rm -rf executes and cleans up. The behaviour is more like ";" operator .

Can someone explain please what am i missing

The issue relates to the exit codes.

The && operator will execute the second command if the first one indicates that it was successful.

consider the following:

gmc@linux-ihon:/tmp> rm -rf nonexistant
gmc@linux-ihon:/tmp> echo $?     # Note that there is no error message and the exit status is 0 (success).
0
gmc@linux-ihon:/tmp> rm -r nonexistant
rm: cannot remove 'nonexistant': No such file or directory
gmc@linux-ihon:/tmp> echo $?     # Note that there was an error message and the exit status is 1 (unsuccessful)
1
gmc@linux-ihon:/tmp> 

So now consider the following:

gmc@linux-ihon:/tmp> rm -rf nonexistant && echo "rm success"
rm success
gmc@linux-ihon:/tmp> rm -r nonexistant && echo "rm success"
rm: cannot remove 'nonexistant': No such file or directory
gmc@linux-ihon:/tmp> 

In this case, because the rm -rf of the nonexistant directory is deemed successful, the next command is executed. Whereas rm -r of the same directory is deemed a failure, so the next command is not executed.

I'm not sure why rm -f returns success when the directory does not exist, one school of thought is that if the directory doesn't exist, then you've achieved the desired outcome of the rm command, so therefore Success! Whereas without the -f option, you are explicitly asking rm to remove something and if it doesn't exist let me know!

BTW. There might be an error in your posted code.

You assign a "bad" directory to the variable dir dir=testdir1 . But you cd $dir1 , this is equivalent to cd with no parameters (because the variable dir1 does not exist). Therefore, it will cd back to your home directory (return value: success). Running rm -rf * from there might not be the best idea.

A command fails means that exit code is different from 0.

If the command should have failed because the variable is not defined set -o nounset or set -u could be used.

set -u
cd "$dir1"
echo "$?"

set +u   # disable nounset
cd "$dir1"
echo "$?"

Checking exit code in documentation or implementation.

from man bash / cd

cd [-L|[-P [-e]] [-@]] [dir]

Change the current directory to dir. if dir is not supplied, the value of the HOME shell variable is the default . Any additional arguments following dir are ignored. The variable CDPATH

defines the search path for the directory containing dir: each directory name in CDPATH is searched for dir. Alternative directory names in CDPATH are separated by a colon (:). A null directory name in CDPATH is the same as the current directory, ie, ``.'' . If dir begins with a slash (/), then CDPATH is not used. The -P option causes cd to use the physical directory structure by

resolving symbolic links while traversing dir and before processing instances of .. in dir (see also the -P option to the set builtin command); the -L option forces symbolic links to be followed

by resolving the link after processing instances of .. in dir. If .. appears in dir, it is processed by removing the immediately previous pathname component from dir, back to a slash or the

beginning of dir. If the -e option is supplied with -P, and the current working directory cannot be successfully determined after a successful directory change, cd will return an unsuccessful

status. On systems that support it, the -@ option presents the extended attributes associated with a file as a directory. An argument of - is converted to $OLDPWD before the directory change is

attempted. If a non-empty directory name from CDPATH is used, or if - is the first argument, and the directory change is successful, the absolute pathname of the new working directory is written

to the standard output. The return value is true if the directory was successfully changed; false otherwise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM