4
\$\begingroup\$

This checks if a font is installed by using fc-list and grep. If the particular font is not installed, it offers to install it for the user. This snippet is part of a larger script that installs a particular Conky configuration along with all of its dependencies with minimal effort from the user.

Concerns

  • I have to create the FONT_INSTALLED variable to avoid a "too many arguments" error by placing the code into the if statement, is there a better practice for handling this?
  • To check if the font is installed, I check if the FONT_INSTALLED variable is a null String or not. Is this considered good practice? I know in languages such as Java a String is normally checked for length/content since the default value is "".
  • I've seen that placing > /dev/null after a command that would normally have output hides the output. This seems slightly 'hacky' as I know commands such as wget have the -q or --quiet option to hide output. For commands that do not have such an option, what is the preferred method of hiding output?

I realize that I should not place semi-colons after each line as per the advice on my first question first question. I forgot to make the appropriate changes to this code snippet.

FONT_INSTALLED=$(fc-list | grep -i "roboto");
if [ -z "$FONT_INSTALLED" ]; then
    echo "The Roboto font is not currently installed, would you like to install it now? (Y/N)";
    read response
    if [[ "$response" == [yY] ]]; then
        echo "Installing the Roboto font to the ~/.fonts directory...";
        mkdir .fonts/Roboto/ -p && wget --quiet -O ~/.fonts/Roboto/tmp.zip http://www.fontsquirrel.com/fonts/download/roboto && 
        unzip ~/.fonts/Roboto/tmp.zip -d ~/.fonts/Roboto/ > /dev/null && rm ~/.fonts/Roboto/tmp.zip 
        fc-cache -fv > /dev/null
        FONT_INSTALLED=$(fc-list | grep -i "roboto");
        if [ -n "$FONT_INSTALLED" ]; then
            echo "The Roboto font was sucessfully installed!";
        else
            echo "Something went wrong while trying to install the Roboto font.";
        fi
    else
        echo "Skipping the installation of the Roboto font...";
        echo "Please note that this Conky configuration will not work without the Roboto font.";
    fi
else
    echo "The Roboto font has already been installed.";
fi
\$\endgroup\$
2
\$\begingroup\$
  • I have to create the FONT_INSTALLED variable to avoid a "too many arguments" error by placing the code into the if statement, is there a better practice for handling this?

You mean this part:

FONT_INSTALLED=$(fc-list | grep -i "roboto");
if [ -z "$FONT_INSTALLED" ]; then

Instead of putting in a variable, you could put the $(...) itself into the if.

A better way would be to leverage the exit of grep in the if directly:

if fc-list | grep -i roboto >/dev/null; then

But since you use this check twice in your code, the best would be to put it in a function:

is_font_installed() {
    fontname=$1
    fc-list | grep -i "$fontname" >/dev/null
}

You could then use this in if statements like this:

if is_font_installed roboto; then
  • To check if the font is installed, I check if the FONT_INSTALLED variable is a null String or not, is this considered good practice? I know in languages such as Java a String is normally checked for length/content since the default value is "".

My previous point answers that: use the exit code of a command when that's all you need.

Btw, there are no real null values in Bash. Null values are just empty strings.

  • I've seen that placing > /dev/null after a command that would normally have output hides the output. This seems slightly 'hacky' as I know commands such as wget have the -q or --quiet option to hide output. For commands that do not have such an option, what is the preferred method of hiding output?

Placing > /dev/null means redirecting standard output to a black hole. It's a fine way to hide output, it's not 'hacky'. It's more verbose than using the -q flag, when such flag exists. But often > /dev/null is more portable than using the -q flag, as the flag might not be available in all implementations. For example grep -q works fine in any Linux, but won't work on some Solaris. So if you want to make your script as portable as possible, it's safest to use the longer > /dev/null instead.

\$\endgroup\$
4
\$\begingroup\$

If you are using then rather than mixing [ and [[, you should stick with one or the other, preferrably [[. See What is the difference between test, [ and [[ ?

You might also want to consider preferring printf over echo for a more robust approach. See this amazingly detailed analysis of why printf is better than echo.

\$\endgroup\$
  • \$\begingroup\$ Nice, and it's especially informative with the links! \$\endgroup\$ – Stop ongoing harm to Monica May 1 '15 at 7:08
2
\$\begingroup\$

To check if the font is installed, I check the FONT_INSTALLED variable

Since you are using grep a more straightforward way is to test its exit status ($?). It is 0 if some lines matched, and 1 if no line matched.

As a general recommendation, a font name shall be passed as an argument. Typing Roboto 12 times is not a good way to spend keystrokes. One day you may want to install another font.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.