Capítulo 20. Bash and Bash Scripts

Sumário

20.1. What is The Shell?
20.2. Writing Shell Scripts
20.3. Redirecting Command Events
20.4. Using Aliases
20.5. Using Variables in Bash
20.6. Grouping And Combining Commands
20.7. Working with Common Flow Constructs
20.8. For More Information

Resumo

These days many people use computers with a graphical user interface (GUI) like KDE or GNOME. Although they offer lots of features, their use is limited when it comes to the execution of automatical tasks. Shells are a good addition to GUIs and this chapter gives you an overview of some aspects of shells, in this case Bash.

20.1. What is The Shell?

Traditionally, the shell is Bash (Bourne again Shell). When this chapter speaks about the shell it means Bash. There are actually more available shells than Bash (ash, csh, ksh, zsh, …), each employing different features and characteristics. If you need further information about other shells, search for shell in YaST.

20.1.1. Knowing The Bash Configuration Files

A shell can be invoked as an:

  1. interactive login shell. This is used when logging in to a machine, invoking Bash with the --login option or when logging in to a remote machine with SSH.

  2. ordinary interactive shell. This is normally the case when starting xterm, konsole, gnome-terminal or similar tools.

  3. non-interactive shell. This is used when invoking a shell script at the commandline.

Depending on which type of shell you use, different configuration files are being read. The following tables show the login and non-login shell configuration files.

Tabela 20.1. Bash Configuration Files for Login Shells

File

Description

/etc/profile

Do not modify this file, otherwise your modifications can be destroyed during your next update!

/etc/profile.local

Use this file if you extend /etc/profile

/etc/profile.d/

Contains system-wide configuration files for specific programs

~/.profile

Insert user specific configuration for login shells here


Tabela 20.2. Bash Configuration Files for Non-Login Shells

/etc/bash.bashrc

Do not modify this file, otherwise your modifications can be destroyed during your next update!

/etc/bash.bashrc.local

Use this file to insert your system-wide modifications for Bash only

~/bashrc

Insert user specific configuration here


Additionally, Bash uses some more files:

Tabela 20.3. Special Files for Bash

File

Description

~/.bash_history

Contains a list of all commands you have been typing

~/.bash_logout

Executed when logging out


20.1.2. A estrutura de diretórios

A seguinte tabela fornece uma breve visão geral dos diretórios mais importantes de alto nível que você encontra em um sistema Linux. Encontre informações mais detalhadas sobre os diretórios e subdiretórios importantes na seguinte lista.

Tabela 20.4. Visão geral de uma árvore de diretórios padrão

Diretório

Conteúdo

/

Diretório raiz—o ponto de início da árvore de diretórios.

/bin

Arquivos executáveis essenciais, como comandos que são necessários tanto para o administrador do sistema como para usuários normais. Geralmente também contém os shells, como o Bash.

/boot

Arquivos estáticos do carregador de inicialização.

/dev

Arquivos necessários para acessar dispositivos específicos da máquina.

/etc

Arquivos de configuração do sistema específicos da máquina.

/home

Contém os diretórios pessoais (home) de todos os usuários que têm contas no sistema. No entanto, o diretório pessoal do root não está localizado em /home mas em /root.

/lib

Bibliotecas compartilhadas essenciais e módulos do kernel.

/media

Pontos de montagem para mídias removíveis.

/mnt

Ponto de montagem para montagem temporária de um sistema de arquivos.

/opt

Pacotes de softwares de aplicativos complementares.

/root

Diretório pessoal para o superusuário root.

/sbin

Executáveis essenciais do sistema.

/srv

Dados para serviços fornecidos pelo sistema.

/tmp

Arquivos temporários.

/usr

Hierarquia secundária com dados somente leitura.

/var

Dados variáveis como arquivos de log.

/windows

Somente disponível se você tem ambos, Microsoft Windows* e Linux, instalados no seu sistema. Contém os dados do Windows.


A lista a seguir fornece informação mais detalhada e fornece alguns exemplos de quais arquivos e subdiretórios podem ser encontrados nos diretórios:

/bin

Contém os comandos básicos do shell que podem ser usados por ambos, o root e outros usuários. Estes comandos incluem o ls, mkdir, cp, mv, rm e rmdir. O diretório /bin também contém o Bash, o shell padrão no openSUSE.

/boot

Contém os dados necessários para a inicialização, como o carregador de inicialização, o kernel e outros dados que são usados antes que o kernel comece a executar os programas no modo usuário.

/dev

Contém os arquivos de dispositivo que representam os componentes de hardware.

/etc

Contém arquivos de configuração local que controlam a operação de programas como o sistema X Window. O subdiretório /etc/init.d contém scripts que são executados durante o processo de inicialização.

/home/nome_de_usuário

Contém os dados privados de cada usuário que tem uma conta no sistema. Os arquivos localizados aqui podem ser modificados somente pelos seus donos ou pelo administrador do sistema. Por padrão, seu diretório de e-mails e configurações pessoais da área de trabalho estão localizados aqui na forma de arquivos e diretórios ocultos. Os usuários do KDE encontram os dados de configuração pessoais para sua área de trabalho em .kde4. Os usuários do GNOME os encontram em .gconf. Para informações sobre arquivos ocultos, consulte Seção “Recursos Chave” (Capítulo 6, Conceitos Básicos, ↑Manual de Incialização).

[Note]Diretório pessoal em um ambiente de rede

Se você estiver trabalhando em um ambiente de rede, seu diretório pessoal pode ser mapeado para um diretório no sistema de arquivos diferente de /home.

/lib

Contém as bibliotecas compartilhadas essenciais necessárias para inicializar o sistema e executar comandos no sistema de arquivos raiz. O equivalente no Windows para as bibliotecas compartilhadas são os arquivos DLL.

/media

Contém pontos de montagem para mídias removíveis como CD-ROMs, pendrives USB e câmeras digitais (se elas forem USB). /media geralmente contém qualquer tipo de unidade, exceto a unidade de disco de seu sistema. Tão logo sua mídia removível seja inserida ou conectada no sistema e montada, você pode acessá-la daqui.

/mnt

Este diretório fornece um ponto de montagem para um sistema de arquivos montado temporariamente. O root pode montar sistemas de arquivos aqui.

/opt

Reservado para a instalação de software de terceiros. Softwares opcionais e pacotes de programas complementares podem ser encontrados aqui.

/root

Diretório pessoal para o usuário root. Os dados pessoais do root estão localizados aqui.

/sbin

Como o s indica, este diretório contém os utilitários para o superusuário. O /sbin contém os executáveis essenciais para a inicialização, restauração e recuperação do sistema em adição aos executáveis do diretório /bin.

/srv

Contém dados para serviços fornecidos pelo sistema, como FTP e HTTP.

/tmp

Este diretório é usado por programas que necessitam de armazenamento temporário de arquivos.

[Important]Limpando o /tmp na inicialização

Os dados armazenados em /tmp não estão garantidos que sobrevivam a uma reinicialização do sistema. Isto depende, por exemplo, da configuração em /etc/sysconfig/cron.

/usr

/usr não tem nada a ver com usuários, mas é o acrônimo para UNIX system resources (recursos do sistema UNIX). Os dados em /usr são estáticos e permitem somente leitura, podendo ser compartilhados entre várias máquinas compatíveis com o FHS (Filesystem Hierarchy Standard - Padrão de Hierarquia de Sistema de Arquivos). Este diretório contém todos os programas aplicativos e estabelece uma segunda hierarquia no sistema de arquivos. O KDE4 e o GNOME também estão localizados aqui. O diretório /usr contém vários subdiretórios, como /usr/bin, /usr/sbin, /usr/local e /usr/share/doc.

/usr/bin

Contém programas geralmente acessíveis.

/usr/sbin

Contém daemons do sistema e programas reservados para o administrador do sistema que não são essenciais para a inicialização do sistema.

/usr/local

Neste diretório, o administrador do sistema pode instalar extensões locais, independentes da distribuição.

/usr/share/doc

Contém vários arquivos de documentação e as notas de lançamento para o seu sistema. No subdiretório manual encontre uma versão online deste manual. Se mais de um idioma estiver instalado, o diretório pode conter versões deste manual para diferentes idiomas.

Em packages encontre a documentação incluída nos pacotes de software instalados no seu sistema. Para cada pacote, um subdiretório /usr/share/doc/packages/nomedopacote é criado, e, frequentemente, contém arquivos README para o pacote e, às vezes, exemplos, arquivos de configuração ou scripts adicionais.

Se HOWTOs estiverem instalados no seu sistema, o /usr/share/doc também conterá o subdiretório howto, no qual você irá encontrar documentação adicional para várias tarefas relacionadas à configuração e operação do software Linux.

/var

Enquanto /usr contém dados estáticos, apenas com permissão de leitura, o diretório /var é para dados que são escritos durante a operação do sistema, e, portanto, são dados variáveis, como arquivos de log ou dados de filas (spooling). Para um resumo dos arquivos de logs mais importantes que você pode encontrar em /var/log/, consulte Tabela “Arquivos de log” (↑Manual de Incialização).

/windows

Disponível somente se você tiver ambos, Microsoft Windows e Linux, instalados no seu sistema. Contém os dados do Windows disponíveis na partição Windows do seu sistema. A possibilidade de edição dos dados neste diretório depende do sistema de arquivos que sua partição Windows usa. Se ele for FAT32, você pode abrir e editar arquivos neste diretório. Para NTFS, o openSUSE também inclui suporte de permissão de escrita. No entanto, o driver para o sistema de arquivos NTFS-3g tem funcionalidade limitada;. Aprenda mais em Seção 34.4, “Accessing Files on Different OS on the Same Computer”.

20.2. Writing Shell Scripts

Shell scripts are a convenient way of doing all sorts of tasks: collecting data, searching for a word or phrase in a text and many other useful things. The following example shows a small shell script that prints a text:

Exemplo 20.1. A Shell Script Printing a Text

#!/bin/sh 1
# Output the following line: 2
echo "Hello World" 3

1

The first line begins with the Shebang characters (#!) which is an indicator that this file is a script. The script is executed with the specified interpreter after the Shebang, in this case /bin/sh.

2

The second line is a comment beginning with the hash sign. It is recommended to comment difficult lines to remember what they do.

3

The third line uses the built-in command echo to print the corresponding text.


Before you can run this script you need some prerequisites:

  1. Every script should contain a Shebang line (this is already the case with our example above.) If a script does not have this line, you have to call the interpreter manually.

  2. You can save the script wherever you want. However, it is a good idea to save it in a directory where the shell can find it. The search path in a shell is determined by the environment variable PATH. Usually a normal user does not have write access to /usr/bin. Therefore it is recommended to save your scripts in the users' directory ~/bin/. The above example gets the name hello.sh.

  3. The script needs executable permissions. Set the permissions with the following command:

    chmod +x ~/bin/hello.sh

If you have fullfilled all of the above prerequisites, you can execute the script in the following ways:

  1. As Absolute Path.  The script can be executed with an absolute path. In our case, it is ~/bin/hello.sh.

  2. Everywhere.  If the PATH environment variable contains the directory where the script is located, you can execute the script just with hello.sh.

20.3. Redirecting Command Events

Each command can use three channels, either for input or output:

  • Standard Output.  This is the default output channel. Whenever a command prints something, it uses the standard output channel.

  • Standard Input.  If a command needs input from users or other commands, it uses this channel.

  • Standard Error.  Commands use this channel for error reporting.

To redirect these channels, there are the following possibilities:

Command > File

Saves the output of the command into a file, an existing file will be deleted. For example, the ls command writes its output into the file listing.txt:

ls > listing.txt
Command >> File

Appends the output of the command to a file. For example, the ls command appends its output to the file listing.txt:

ls >> listing.txt
Command < File

Reads the file as input for the given command. For example, the read command reads in the content of the file into the variable a:

read a < foo
Command1 | Command2

Redirects the output of the left command as input for the right command. For example, the cat command outputs the content of the /proc/cpuinfo file. This output is used by grep to filter only those lines which contain cpu:

cat /proc/cpuinfo | grep cpu

Every channel has a file descriptor: 0 (zero) for standard input, 1 for standard output and 2 for standard error. It is allowed to insert this file descriptor before a < or > character. For example, the following line searches for a file starting with foo, but suppresses its errors by redirecting it to /dev/null, the garbage bin:

find / -name "foo*" 2>/dev/null

20.4. Using Aliases

An alias is a shortcut definition of one or more commands. This is useful if you have commands which are hard to remember or with lots of options. The syntax for an alias is:

alias NAME=DEFINITION

For example, the following line defines an alias lt which outputs a long listing (option -l), sorts it by modification time (-t) and prints it in reverse order while sorting (-r):

alias lt='ls -ltr'

To view all alias definitions, use alias. Remove your alias with unalias.

20.5. Using Variables in Bash

A shell variable can be global or local. Global variables, or environment variables, can be accessed in all shells. In contrast, local variables are visible in the current shell only.

To view all environment variables, use the printenv command. If you need to know the value of a variable, insert the name of your variable as an argument:

printenv PATH

A variable, be it global or local, can also be viewed with echo:

echo $PATH

To set a local variable, use a variable name followed by the equal sign, followed by the value:

PROJECT="SLED"

Do not insert spaces around the equal sign, otherwise you get an error. To set a environment variable, use export:

export NAME="tux"

To remove a variable, use unset:

unset NAME

The following table contains some common environment variables which can be used in you shell scripts:

Tabela 20.5. Useful Environment Variables

HOME

the home directory of the current user

HOST

the current host name

LANG

when a tool is localized, it uses the language from this environment variable. English can also be set to C

PATH

the search path of the shell, a list of directories separated by colon

PS1

specifies the normal prompt printed before each command

PS2

specifies the secondary prompt printed when you execute a multi-line command

PWD

current working directory

USER

the current user


20.5.1. Using Argument Variables

For example, if you have the script foo.sh you can execute it like this:

foo.sh "Tux Penguin" 2000 

To access all the arguments which are passed to your script, you need positional parameters. These are $1 for the first argument, $2 for the second, and so on. You can have up to nine parameters. To get the script name, use $0.

The following script foo.sh prints all arguments from 1 to 4:

#!/bin/sh
echo \"$1\" \"$2\" \"$3\" \"$4\"

If you execute this script with the above arguments, you get:

"Tux Penguin" "2000" "" ""

20.5.2. Using Variable Substitution

Variable substitutions apply a pattern to the content of a variable either from the left or right side. The following list contains the possible syntax forms:

${VAR#pattern}

removes the shortest possible match from the left:

file=/home/tux/book/book.tar.bz2
echo ${file#*/}
home/tux/book/book.tar.bz2
${VAR##pattern}

removes the longest possible match from the left:

file=/home/tux/book/book.tar.bz2
echo ${file##*/}
book.tar.bz2
${VAR%pattern}

removes the shortest possible match from the right:

file=/home/tux/book/book.tar.bz2
echo ${file%.*}
/home/tux/book/book.tar
${VAR%%pattern}

removes the longest possible match from the right:

file=/home/tux/book/book.tar.bz2
echo ${file%%.*}
/home/tux/book/book
${VAR/pattern_1/pattern_2}

substitutes the content of VAR from the pattern_1 with pattern_2:

file=/home/tux/book/book.tar.bz2
echo ${file/tux/wilber}
/home/wilber/book/book.tar.bz2

20.6. Grouping And Combining Commands

Shells allow you to concatenate and group commands for conditional execution. Each command returns an exit code which determines the success or failure of its operation. If it is 0 (zero) the command was successful, everything else marks an error which is specific to the command.

The following list shows, how commands can be grouped:

Command1 ; Command2

executes the commands in sequential order. The exit code is not checked. The following line displays the content of the file with cat and then prints its file properties with ls regardless of their exit codes:

cat filelist.txt ; ls -l filelist.txt
Command1 && Command2

runs the right command, if the left command was successful (logical AND). The following line displays the content of the file and prints its file properties only, when the previous command was successful (compare it with the previous entry in this list):

cat filelist.txt && ls -l filelist.txt
Command1 || Command2

runs the right command, when the left command has failed (logical OR). The following line creates only a directory in /home/wilber/bar when the creation of the directory in /home/tux/foo has failed:

mkdir /home/tux/foo || mkdir /home/wilber/bar
funcname(){ ... }

creates a shell function. You can use the positional parameters to access its arguments. The following line defines the function hello to print a short message:

hello() { echo "Hello $1"; }

You can call this function like this:

hello Tux

which prints:

Hello Tux

20.7. Working with Common Flow Constructs

To control the flow of your script, a shell has while, if, for and case constructs.

20.7.1. The if Control Command

The if command is used to check expressions. For example, the following code tests whether the current user is Tux:

if test $USER = "tux" ;then
  echo "Hello Tux."
else
  echo "You are not Tux."
fi

The test expression can be as complex or simple as possible. The following expression checks if the file foo.txt exists:

if test -e /tmp/foo.txt ; then
  echo "Found foo.txt"
fi

The test expression can also be abbreviated in angled brackets:

if [ -e /tmp/foo.txt ] ; then
  echo "Found foo.txt"
fi

Find more useful expressions at http://www.cyberciti.biz/nixcraft/linux/docs/uniqlinuxfeatures/lsst/ch03sec02.html.

20.7.2. Creating Loops With The For Command

The for loop allows you to execute commands to a list of entries. For example, the following code prints some information about PNG files in the current directory:

for i in *.png; do
 ls -l $i
done

20.8. For More Information

Important information about Bash is provided in the man pages man sh. More about this topic can be found in the following list: