shell

Meaning of "! -S" in shell script


I am new to shell scripting, and I have encountered a script I didn't understand:

DOWN=true
while $DOWN; do
    sleep 0.1
    DOWN=false
    for i in {1..7}
    do
    if [ ! -S "qdata/c$i/tm.ipc" ]; then
            DOWN=true
    fi
    done
done

Specifically, what does this command mean:

! -S "qdata/c$i/tm.ipc"

Solution

  • The command you are looking at is actually this:

    [ ! -S "qdata/c$i/tm.ipc" ]
    

    Although it looks like punctuation, [ is actually the name of a command, also called test; so the command can also be written like this:

    test ! -S "qdata/c$i/tm.ipc"
    

    Which in context would look like this:

    if test ! -S "qdata/c$i/tm.ipc"; then
            DOWN=true
    fi
    

    As the name suggests, its job is to test some attribute of a string, number, or file, and return 0 (which represents success/true in shell scripts) if the test passes, and 1 (which represents failure/false) if it doesn't.

    Armed with this knowledge, you can run man test, and find the following explanations of the ! and -S arguments:

       ! EXPRESSION
             EXPRESSION is false
    

    and

       -S FILE
             FILE exists and is a socket
    

    So test ! -S filename or [ ! -S filename ] can be read as "not is-socket filename".

    So the command is checking whether a "socket" (a special kind of file) exists with each name in the loop. The script uses this command as the argument to an if statement (which can take any command, not just [) and sets DOWN to true if any of them does not exist.