zoukankan      html  css  js  c++  java
  • Learning_the_bash_Shell_Third_Edition 10/n

    Flow Control

     Exit Status

    Every UNIX command, whether it comes from source code in C, some other language, or a shell script/function, returns an integer code to its calling process—the shell in this case—when it finishes. This is called the exit status. 0 is usually the OK exit status, while anything else (1 to 255) usually denotes an error.

    pushd ( )
    {
    dirname=$1
    DIR_STACK="$dirname ${DIR_STACK:-$PWD' '}"
    cd ${dirname:?"missing directory name."}
    echo $DIR_STACK
    }
    

      

    This function requires a valid directory as its argument. Let’s look at how it handles error conditions: if no argument is given, the third line of code prints an error message and exits. This is fine.

    However, the function reacts deceptively when an argument is given that isn’t a valid directory. In case you didn’t figure it out when reading the last chapter, here is what happens: the cd fails, leaving you in the same directory you were in. This is also appropriate. But the second line of code has pushed the bad directory onto the stack anyway, and the last line prints a message that leads you to believe that the push was successful. Even placing the cd before the stack assignment won’t help because it doesn’t exit the function if there is an error.

    We need to prevent the bad directory from being pushed and to print an error message. Here is how we can do this:

    pushd ( )
    {
    dirname=$1
    if cd ${dirname:?"missing directory name."}
    # if cd was successful
    then
    DIR_STACK="$dirname ${DIR_STACK:-$PWD' '}" # push the directory
    echo $DIR_STACK
    else
    echo still in $PWD.
    # else do nothing
    fi
    }
    

    Let’s say you have the following code in your .bash_profile.

    cd ( )
    {
    builtin cd "$@"
    echo "$OLDPWD —> $PWD"
    }
    

      

    The builtin command allows us to do this. builtin tells the shell to use the built-in command and ignore any function of that name. Using builtin is easy; you just give it the name of the built-in you want to execute and any parameters you want to pass. If you pass in the name of something which isn’t a built-in command, builtin will display an appropriate message. For example: builtin: alice: not a shell builtin.

    We want this function to return the same exit status that the built-in cd returns. The problem is that the exit status is reset by every command, so it “disappears” if you don’t save it immediately. In this function, the built-in cd’s exit status disappears when the echo statement runs (and sets its own exit status).

    Therefore, we need to save the status that cd sets and use it as the entire function’s exit status. Two shell features we haven’t seen yet provide the way. First is the special shell variable ?, whose value ($?) is the exit status of the last command that ran.

    For example:

    So, to save the exit status we need to assign the value of ? to a variable with the line es=$? right after the cd is done.

     Return

    return can only be used inside functions, and shell scripts that have been executed with source. In contrast, the statement exit N exits the entire script, no matter how deeply you are

    nested in functions.

    cd ( )
    {
    builtin cd "$@"
    es=$?
    echo "$OLDPWD —> $PWD"
    return $es
    }
    

      Combinations of Exit Statuses

      

    statement1 && statement2

    The syntax statement1 && statement2 means, “execute statement1, and if its exit status is 0, execute statement2.”

    tatement1 || statement2 

     

    The syntax statement1 || statement2 is the converse: it means, “execute statement1, and if its exit status is not 0, execute statement2.”

    Condition Tests

     

    [ condition ]
    

      String comparisons

    Operator

    True if...

    str1 = str2

    str1 matches str2

    str1 != str2

    str1 does not match str2

    str1 < str2

    str1 is less than str2

    str1 > str2

    str1 is greater than str2

    -n str1

    str1 is not null (has length greater than 0)

    -z str1

    str1 is null (has length 0)

     File attribute checking

    Operator

    True if...

    -a file

    file exists

    -d file

    file exists and is a directory

    -e file

    file exists; same as -a

    -f file

    file exists and is a regular file (i.e., not a directory or other special type of file)

    -r file

    You have read permission on file

    -s file

    file exists and is not empty

    -w file

    You have write permission on file

    -x file

    You have execute permission on file, or directory search permission if it is a directory

    -N file

    file was modified since it was last read

    -O file

    You own file

    -G file

    file’s group ID matches yours (or one of yours, if you are in multiple groups)

    file1 -nt file2

    file1 is newer than file2

    file1 -ot file2

    file1 is older than file2

    You can also negate the truth value of a conditional expression by preceding it with an exclamation point (!), so that ! expr evaluates to true only if expr is false. Furthermore, you can make complex logical expressions of conditional operators by grouping them with parentheses (which must be “escaped” with backslashes to prevent the shell from treating them specially), and by using two logical operators we haven’t seen yet: -a (AND) and -o (OR).

    The -a and -o operators are similar to the && and || operators used with exit statuses. However, unlike those operators, -a and -o are only available inside a test conditional expression.

    Here is how we would use two of the file operators, a logical operator, and a string operator to fix the problem of duplicate stack entries in our pushd function. Instead of having cd determine whether the argument given is a valid directory—i.e., by returning with a bad exit status if it’s not—we can do the checking ourselves. Here is the code:

    pushd ( )
    {
    dirname=$1
    if [ -n "$dirname" ] && [ ( -d "$dirname" ) -a 
    ( -x "$dirname" ) ]; then
    DIR_STACK="$dirname ${DIR_STACK:-$PWD' '}"
    cd $dirname
    echo "$DIR_STACK"
    else
    echo "still in $PWD."
    fi
    }
    

      

    The conditional expression evaluates to true only if the argument $1 is not null (-n), a directory (-d) and the user has permission to change to it (-x). * Notice that this conditional handles the case where the argument is missing ($dirname is null) first; if it is,the rest of the condition is not executed. This is important because, if we had just put:

    if [ ( -n "$dirname") -a ( -d "$dirname" ) -a 
    ( -x "$dirname" ) ]; then
    

    Task 5-1

    Write a script that prints essentially the same information as ls -l but in a more user friendly way.

    #

    if [ ! -e "$1" ]; then
    echo "file $1 does not exist."
    exit 1
    fi
    if [ -d "$1" ]; then
    echo -n "$1 is a directory that you may "
    if [ ! -x "$1" ]; then
    echo -n "not "
    fi
    echo "search."
    elif [ -f "$1" ]; then
    echo "$1 is a regular file."
    else
    echo "$1 is a special type of file."
    fi
    if [ -O "$1" ]; then
    echo 'you own the file.'
    else
    echo 'you do not own the file.'
    fi
    if [ -r "$1" ]; then
    echo 'you have read permission on the file.'
    fi
    if [ -w "$1" ]; then
    echo 'you have write permission on the file.'
    fi
    if [ -x "$1" -a ! -d "$1" ]; then
    echo 'you have execute permission on the file.'
    fi
    

      

  • 相关阅读:
    pe文件结构
    dll
    术语
    创建内存映射文件
    函数的调用约定
    串口
    linux 之 tcpdump
    linux 之程序管理
    perl 之eval
    2020-10-27_组合快捷键
  • 原文地址:https://www.cnblogs.com/winditsway/p/14478984.html
Copyright © 2011-2022 走看看