简体   繁体   中英

What does the if [ “${-#*i}” != “$-” ] mean?

In my Oracle Linux box, I found a block of script in /etc/profile that is hard to figure out:

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

My question is the variables in the if statement ${-#*i} and $- . What does that mean? And why should add an else statement to redirect output? Thanks!

$- is a variable which stores the current options set by the shell .

${-#*i} is using substring removal to remove the shortest match to the pattern *i from the beginning of the variable. So if $- has the value abcifOO then ${-#*i} would be fOO . (You can read more about bash substrings here.)

This means that the test

[ "${-#*i}" != "$-" ]

will be true if the variable $- contains the option i , which means interactive mode is switched on.

All together this means that the output will only be redirected to /dev/null if you are in interactive mode.

It's checking whether the shell is interactive. The current shell's options are in $- and if removing anything followed by i yields a different result, it means that i was among the flags.

This would be a lot more readable and idiomatic, though:

case $- in *i* ) ... ;; esac

Also, it would be better to do the check once, outside the loop.

What does $- mean?

From the manual:

-

(A hyphen.) Expands to the current option flags as specified upon invocation, by the set builtin command, or those set by the shell itself (such as the -i option).

When you're running bash interactively , then $- might exapnd to something like:

himBH

When you're executing a script, $- wouldn't have i (apart from some other flags above).

What does ${-#*i} mean?

Saying ${-#*i} causes the shortest match of *i from the beginning of the expansion of $- to be deleted. (Refer to Shell Parameter Expansion .)

In short, the inner if conditional in the example implies that while in the interactive mode the following is executed:

. "$i" >/dev/null 2>&1

and in the non-interactive mode, the following:

. "$i"

Just to add up a little more detail about $-. if you try to type in your terminal

[root@zee ~]# echo $-
himBH

Those appear to be shell 'set' values

Snippets from info bash --index-search=set

 '-h'

Locate and remember (hash) commands as they are looked up for execution. This option is enabled by default.

 '-m'

Job control is enabled (*note Job Control::).

 '-B'

The shell will perform brace expansion (*note Brace Expansion::). This option is on by default.

'-H'

Enable '!' style history substitution (*note History Interaction::). This option is on by default for interactive shells.

Using +' rather than -' causes these options to be turned off. The options can also be used upon invocation of the shell.

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