-
Notifications
You must be signed in to change notification settings - Fork 268
Expand file tree
/
Copy pathadm_shell.xml
More file actions
1020 lines (974 loc) · 28.1 KB
/
adm_shell.xml
File metadata and controls
1020 lines (974 loc) · 28.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0"?>
<!DOCTYPE chapter [
<!ENTITY % entities SYSTEM "generic-entities.ent">
%entities;
]>
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="cha-adm-shell">
<!-- Better Title? -->
<title>Bash and Bash Scripts</title>
<info>
<meta name="description">Manage tasks and automate processes with the Bash shell using its powerful commands and features, then apply your newfound skills in practice</meta>
<abstract>
<para>
Today, many people use computers with a graphical user interface (GUI)
like &gnome;. Although they offer lots of features, their use is limited
when it comes to the execution of automated tasks. Shells are a good
addition to GUIs and this chapter gives you an overview of some aspects of
shells, in this case Bash.
</para>
</abstract>
<dm:docmanager xmlns:dm="urn:x-suse:ns:docmanager">
<dm:bugtracker/>
<dm:translation>yes</dm:translation>
</dm:docmanager>
<revhistory xml:id="rh-cha-adm-shell">
<revision>
<date>2026-04-09</date>
<revdescription>
<para/>
</revdescription>
</revision>
</revhistory>
</info>
<sect1 xml:id="sec-adm-whatistheshell">
<title>What is <quote>The Shell</quote>?</title>
<!--<para>A shell is a fundamental part of each Linux system: Its user
interface allow users to enter commands to execute different
tasks, like listing of directories, showing files, or searching
for files.</para>-->
<para>
Traditionally, <emphasis>the</emphasis> Linux shell is Bash
(Bourne again Shell). When this chapter speaks about <quote>the shell</quote>
it means Bash. There are more shells available (ash, csh, ksh, zsh, …),
each employing different features and characteristics.
</para>
<sect2 xml:id="sec-adm-configfiles">
<title>Knowing the Bash Configuration Files</title>
<para>
A shell can be invoked as an:
</para>
<orderedlist spacing="normal">
<listitem>
<formalpara>
<title>Interactive login shell</title>
<para>
This is used when logging in to a machine, invoking Bash with the
<option>--login</option> option or when logging in to a remote machine
with SSH.
</para>
</formalpara>
</listitem>
<listitem>
<formalpara>
<title>Interactive non-login shell</title>
<para>
This is normally the case when starting xterm, konsole, gnome-terminal
or similar tools.
</para>
</formalpara>
</listitem>
<listitem>
<formalpara>
<title>Non-interactive non-login shell</title>
<para>
This is used when invoking a shell script at the command line.
</para>
</formalpara>
</listitem>
</orderedlist>
<para>
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.
</para>
<tip>
<para>
Bash looks for its configuration files in a specific order depending on
the type of shell where it is run. Find more details on the Bash man
page (<command>man 1 bash</command>). Search for the headline
<literal>INVOCATION</literal>.
</para>
</tip>
<table xml:id="tab-adm-shell-config-loginshells">
<title>Bash Configuration Files for Login Shells</title>
<tgroup cols="2">
<thead>
<row>
<entry>
<para>
File
</para>
</entry>
<entry>
<para>
Description
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
<filename>/etc/profile</filename>
</para>
</entry>
<entry>
<para>
Do not modify this file, otherwise your modifications can be destroyed
during your next update!
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>/etc/profile.local</filename>
</para>
</entry>
<entry>
<para>
Use this file if you extend <filename>/etc/profile</filename>
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>/etc/profile.d/</filename>
</para>
</entry>
<entry>
<para>
Contains system-wide configuration files for specific programs
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>~/.profile</filename>
</para>
</entry>
<entry>
<para>
Insert user specific configuration for login shells here
</para>
</entry>
</row>
<!-- -->
</tbody>
</tgroup>
</table>
<para>
Note that the login shell also sources the configuration files listed under
<xref linkend="tab-adm-shell-configs-nonloginshells"/>.
</para>
<table xml:id="tab-adm-shell-configs-nonloginshells">
<title>Bash Configuration Files for Non-Login Shells</title>
<tgroup cols="2">
<tbody>
<row>
<entry>
<para>
<filename>/etc/bash.bashrc</filename>
</para>
</entry>
<entry>
<para>
Do not modify this file, otherwise your modifications can be destroyed
during your next update!
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>/etc/bash.bashrc.local</filename>
</para>
</entry>
<entry>
<para>
Use this file to insert your system-wide modifications for Bash only
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>~/.bashrc</filename>
</para>
</entry>
<entry>
<para>
Insert user specific configuration here
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Additionally, Bash uses some more files:
</para>
<table>
<title>Special Files for Bash</title>
<tgroup cols="2">
<thead>
<row>
<entry>
<para>
File
</para>
</entry>
<entry>
<para>
Description
</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>
<filename>~/.bash_history</filename>
</para>
</entry>
<entry>
<para>
Contains a list of all commands you have been typing
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>~/.bash_logout</filename>
</para>
</entry>
<entry>
<para>
Executed when logging out
</para>
</entry>
</row>
<row>
<entry>
<para>
<filename>~/.alias</filename>
</para>
</entry>
<entry>
<para>
User defined aliases of frequently used commands. See
<command>man 1 alias</command> for more details about how to define
aliases.
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<xi:include href="fs_structure_i.xml"/>
</sect1>
<sect1 xml:id="sec-adm-shellscripts">
<title>Writing Shell Scripts</title>
<para>
Shell scripts provide a convenient way to perform a wide range of tasks: collecting
data, searching for a word or phrase in a text and other useful things.
The following example shows a small shell script that prints a text:
</para>
<example>
<title>A Shell Script Printing a Text</title>
<screen>#!/bin/sh <co xml:id="co-adm-shell-shebang"/>
# Output the following line: <co xml:id="co-adm-shell-comment"/>
echo "Hello World" <co xml:id="co-adm-shell-echo"/></screen>
<calloutlist>
<callout arearefs="co-adm-shell-shebang">
<para>
The first line begins with the <emphasis>Shebang</emphasis>
characters (<literal>#!</literal>) which is an indicator
that this file is a script. The script is executed with the specified
interpreter after the Shebang, in this case <command>/bin/sh</command>.
</para>
</callout>
<callout arearefs="co-adm-shell-comment">
<para>
The second line is a comment beginning with the hash sign. It is
recommended to comment difficult lines to remember what they do.
</para>
</callout>
<callout arearefs="co-adm-shell-echo">
<para>
The third line uses the built-in command <command>echo</command> to print
the corresponding text.
</para>
</callout>
</calloutlist>
</example>
<para>
Before you can run this script you need some prerequisites:
</para>
<orderedlist spacing="normal">
<listitem>
<para>
Every script should contain a Shebang line (as in the example above). If
the line is missing, you need to call the interpreter manually.
</para>
</listitem>
<listitem>
<para>
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 <envar>PATH</envar>.
Usually a normal user does not have write access to
<filename>/usr/bin</filename>. Therefore it is recommended to save your
scripts in the users' directory <filename>~/bin/</filename>. The above
example gets the name <filename>hello.sh</filename>.
</para>
</listitem>
<listitem>
<para>
The script needs executable permissions. Set the permissions with the
following command:
</para>
<screen>chmod +x ~/bin/hello.sh</screen>
</listitem>
</orderedlist>
<para>
If you have fulfilled all of the above prerequisites, you can execute the
script in the following ways:
</para>
<orderedlist spacing="normal">
<listitem>
<formalpara>
<title>As Absolute Path</title>
<para>
The script can be executed with an absolute path. In our case, it is
<command>~/bin/hello.sh</command>.
</para>
</formalpara>
</listitem>
<listitem>
<formalpara>
<title>Everywhere</title>
<para>
If the <envar>PATH</envar> environment variable contains the directory
where the script is located, you can execute the script with
<command>hello.sh</command>.
</para>
</formalpara>
</listitem>
</orderedlist>
</sect1>
<sect1 xml:id="sec-adm-shell-redirect">
<title>Redirecting Command Events</title>
<para>
Each command can use three channels, either for input or output:
</para>
<itemizedlist mark="bullet" spacing="normal">
<listitem>
<formalpara>
<title>Standard Output</title>
<para>
This is the default output channel. Whenever a command prints something,
it uses the standard output channel.
</para>
</formalpara>
</listitem>
<listitem>
<formalpara>
<title>Standard Input</title>
<para>
If a command needs input from users or other commands, it uses this
channel.
</para>
</formalpara>
</listitem>
<listitem>
<formalpara>
<title>Standard Error</title>
<para>
Commands use this channel for error reporting.
</para>
</formalpara>
</listitem>
</itemizedlist>
<para>
To redirect these channels, there are the following possibilities:
</para>
<variablelist>
<varlistentry>
<term><literal>Command > File</literal>
</term>
<listitem>
<para>
Saves the output of the command into a file, an existing file will be
deleted. For example, the <command>ls</command> command writes its output
into the file <filename>listing.txt</filename>:
</para>
<screen>ls > listing.txt</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Command >> File</literal>
</term>
<listitem>
<para>
Appends the output of the command to a file. For example, the
<command>ls</command> command appends its output to the file
<filename>listing.txt</filename>:
</para>
<screen>ls >> listing.txt</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Command < File</literal>
</term>
<listitem>
<para>
Reads the file as input for the given command. For example, the
<command>read</command> command reads in the content of the file into the
variable:
</para>
<screen>read a < foo</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Command1 | Command2</literal>
</term>
<listitem>
<para>
Redirects the output of the left command as input for the right command.
For example, the <command>cat</command> command outputs the content of
the <filename>/proc/cpuinfo</filename> file. This output is used by
<command>grep</command> to filter only those lines which contain
<literal>cpu</literal>:
</para>
<screen>cat /proc/cpuinfo | grep cpu</screen>
</listitem>
</varlistentry>
</variablelist>
<para>
Every channel has a <emphasis>file descriptor</emphasis>: 0 (zero) for
standard input, 1 for standard output and 2 for standard error. It is
allowed to insert this file descriptor before a <literal><</literal> or
<literal>></literal> character. For example, the following line searches
for a file starting with <filename>foo</filename>, but suppresses its errors
by redirecting it to <filename>/dev/null</filename>:
</para>
<screen>find / -name "foo*" 2>/dev/null</screen>
</sect1>
<sect1 xml:id="sec-adm-alias">
<title>Using Aliases</title>
<para>
An alias is a shortcut definition of one or more commands. The syntax for an
alias is:
</para>
<screen>alias <replaceable>NAME</replaceable>=<replaceable>DEFINITION</replaceable></screen>
<para>
For example, the following line defines an alias <command>lt</command> that
outputs a long listing (option <option>-l</option>), sorts it by
modification time (<option>-t</option>), and prints it in reverse sorted order (<option>-r</option>):
</para>
<screen>alias lt='ls -ltr'</screen>
<para>
To view all alias definitions, use <command>alias</command>. Remove your
alias with <command>unalias</command> and the corresponding alias name.
</para>
</sect1>
<sect1 xml:id="sec-adm-variables">
<title>Using Variables in Bash</title>
<para>
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.
</para>
<para>
To view all environment variables, use the <command>printenv</command>
command. If you need to know the value of a variable, insert the name of
your variable as an argument:
</para>
<screen>printenv PATH</screen>
<para>
A variable, be it global or local, can also be viewed with
<command>echo</command>:
</para>
<screen>echo $PATH</screen>
<para>
To set a local variable, use a variable name followed by the equal sign,
followed by the value:
</para>
<screen>PROJECT="SLED"</screen>
<para>
Do not insert spaces around the equal sign, otherwise you get an error. To
set an environment variable, use <command>export</command>:
</para>
<screen>export NAME="tux"</screen>
<para>
To remove a variable, use <command>unset</command>:
</para>
<screen>unset NAME</screen>
<para>
The following table contains some common environment variables which can be
used in you shell scripts:
</para>
<table xml:id="tab-adm-envars">
<title>Useful Environment Variables</title>
<tgroup cols="2">
<tbody>
<row>
<entry>
<para>
<envar>HOME</envar>
</para>
</entry>
<entry>
<para>
the home directory of the current user
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>HOST</envar>
</para>
</entry>
<entry>
<para>
the current host name
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>LANG</envar>
</para>
</entry>
<entry>
<para>
when a tool is localized, it uses the language from this environment
variable. English can also be set to <literal>C</literal>
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>PATH</envar>
</para>
</entry>
<entry>
<para>
the search path of the shell, a list of directories separated by colon
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>PS1</envar>
</para>
</entry>
<entry>
<para>
specifies the normal prompt printed before each command
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>PS2</envar>
</para>
</entry>
<entry>
<para>
specifies the secondary prompt printed when you execute a multi-line
command
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>PWD</envar>
</para>
</entry>
<entry>
<para>
current working directory
</para>
</entry>
</row>
<row>
<entry>
<para>
<envar>USER</envar>
</para>
</entry>
<entry>
<para>
the current user
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
<sect2 xml:id="sec-adm-variables-argument">
<title>Using Argument Variables</title>
<!-- toms 2008-11-04: TODO: Argument Variables
$0...$9 positional argument
$* all arguments
$# number of arguments
$@ all arguments with spaces
-->
<para>
For example, if you have the script <command>foo.sh</command> you can
execute it like this:
</para>
<screen>foo.sh "Tux Penguin" 2000 </screen>
<para>
To access all the arguments which are passed to your script, you need
positional parameters. These are <envar>$1</envar> for the first argument,
<envar>$2</envar> for the second, and so on. You can have up to nine
parameters. To get the script name, use <envar>$0</envar>.
</para>
<para>
The following script <command>foo.sh</command> prints all arguments from 1
to 4:
</para>
<screen>#!/bin/sh
echo \"$1\" \"$2\" \"$3\" \"$4\"</screen>
<para>
If you execute this script with the above arguments, you get:
</para>
<screen>"Tux Penguin" "2000" "" ""</screen>
<!--
<table id="tab-adm-shell-argvar">
<title>Argument Variables</title>
<tgroup cols="2">
<thead>
<row>
<entry>
<para>Form</para>
</entry>
<entry>
<para>Meaning</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<screen>${VAR?message}</screen>
</entry>
<entry>
<para>prints the message and complains, if variable
<replaceable>VAR</replaceable> is undefinied</para>
<screen>echo ${FOO?'Not definied'}
bash: FOO: Not definied</screen>
</entry>
</row>
<row>
<entry>
<screen>${VAR-default}</screen>
</entry>
<entry>
<para>return a default value, if variable
<replaceable>VAR</replaceable> is undefinied but do
not define the variable</para>
<screen>echo ${FOO-Hi}
Hi
echo Variable \"$FOO\"
Variable ""</screen>
</entry>
</row>
<row>
<entry>
<screen>${VAR+value}</screen>
</entry>
<entry>
<para>if the variable <replaceable>VAR</replaceable> is
definied, return its new value but keep it unchanged</para>
<screen>FOO=Hi
echo ${FOO+Hello}
Hello
echo $FOO
Hi</screen>
</entry>
</row>
<row>
<entry>
<screen>${VAR=value}</screen>
</entry>
<entry>
<para>if the variable <replaceable>VAR</replaceable> is
undefinied, define it and assign the value to it:</para>
<screen>unset FOO
echo ${FOO="Hello World"}
"Hello World"
x=2
echo ${x=3}
2</screen>
</entry>
</row>
</tbody>
</tgroup>
</table>
-->
</sect2>
<sect2 xml:id="sec-adm-shell-varsubst">
<title>Using Variable Substitution</title>
<para>
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:
</para>
<variablelist>
<varlistentry>
<term><literal>${VAR#pattern}</literal>
</term>
<listitem>
<para>
removes the shortest possible match from the left:
</para>
<screen>file=/home/tux/book/book.tar.bz2
echo ${file#*/}
home/tux/book/book.tar.bz2</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>${VAR##pattern}</literal>
</term>
<listitem>
<para>
removes the longest possible match from the left:
</para>
<screen>file=/home/tux/book/book.tar.bz2
echo ${file##*/}
book.tar.bz2</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>${VAR%pattern}</literal>
</term>
<listitem>
<para>
removes the shortest possible match from the right:
</para>
<screen>file=/home/tux/book/book.tar.bz2
echo ${file%.*}
/home/tux/book/book.tar</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>${VAR%%pattern}</literal>
</term>
<listitem>
<para>
removes the longest possible match from the right:
</para>
<screen>file=/home/tux/book/book.tar.bz2
echo ${file%%.*}
/home/tux/book/book</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>${VAR/pattern_1/pattern_2}</literal>
</term>
<listitem>
<para>
substitutes the content of <replaceable>VAR</replaceable> from the
<replaceable>PATTERN_1</replaceable> with
<replaceable>PATTERN_2</replaceable>:
</para>
<screen>file=/home/tux/book/book.tar.bz2
echo ${file/tux/wilber}
/home/wilber/book/book.tar.bz2</screen>
</listitem>
</varlistentry>
</variablelist>
<!--
toms 2008-11-04: TODO: Add variable substitution:
${V:-def} $V, or "def" if unset
${V:+def} if $V is empty, it stays empty, otherwise
replace it with "def"
${V:=def} $V set to "def" if unset
${V:?err} $V, or output "err" if unset
${V#pattern}
${V##pattern}
${V%pattern}
${V%%pattern}
${!V} similar to \$${V}
-->
</sect2>
</sect1>
<sect1 xml:id="sec-adm-shell-grouping">
<title>Grouping and Combining Commands</title>
<para>
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.
</para>
<para>
The following list shows, how commands can be grouped:
</para>
<variablelist>
<varlistentry>
<term><literal>Command1 ; Command2</literal>
</term>
<listitem>
<para>
executes the commands in sequential order. The exit code is not checked.
The following line displays the content of the file with
<command>cat</command> and then prints its file properties with
<command>ls</command> regardless of their exit codes:
</para>
<screen>cat filelist.txt ; ls -l filelist.txt</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Command1 && Command2</literal>
</term>
<listitem>
<para>
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):
</para>
<screen>cat filelist.txt && ls -l filelist.txt</screen>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>Command1 || Command2</literal>
</term>
<listitem>
<para>
runs the right command, when the left command has failed (logical OR).
The following line creates only a directory in
<filename>/home/wilber/bar</filename> when the creation of the directory
in <filename>/home/tux/foo</filename> has failed:
</para>
<screen>mkdir /home/tux/foo || mkdir /home/wilber/bar</screen>
</listitem>
</varlistentry>
<!--<varlistentry>
<term><literal>{ Command1 ; Command2 }</literal></term>
<listitem>
<para>group the commands in the curley brackets and run it in
the current shell.</para>
</listitem>
</varlistentry>-->
<varlistentry>
<term><literal>funcname(){ ... }</literal>
</term>
<listitem>
<para>
creates a shell function. You can use the positional parameters to access
its arguments. The following line defines the function
<literal>hello</literal> to print a short message:
</para>
<screen>hello() { echo "Hello $1"; }</screen>
<para>
You can call this function like this:
</para>
<screen>hello Tux</screen>
<para>
which prints:
</para>
<screen>Hello Tux</screen>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1 xml:id="sec-adm-shell-commonconstructs">
<title>Working with Common Flow Constructs</title>
<para>
To control the flow of your script, a shell has <command>while</command>,
<command>if</command>, <command>for</command> and <command>case</command>
constructs.
</para>
<!-- toms: Explaining test expressions? -->
<sect2 xml:id="sec-adm-shell-if">
<title>The if Control Command</title>
<para>
The <command>if</command> command is used to check expressions. For
example, the following code tests whether the current user is Tux:
</para>
<screen>if test $USER = "tux"; then
echo "Hello Tux."
else
echo "You are not Tux."
fi</screen>
<para>
The test expression can be as complex or simple as possible. The following
expression checks if the file <filename>foo.txt</filename> exists:
</para>
<screen>if test -e /tmp/foo.txt ; then
echo "Found foo.txt"
fi</screen>
<para>
The test expression can also be abbreviated in angled brackets:
</para>
<screen>if [ -e /tmp/foo.txt ] ; then
echo "Found foo.txt"
fi</screen>
<para>
Find more useful expressions at
<link xlink:href="http://www.cyberciti.biz/nixcraft/linux/docs/uniqlinuxfeatures/lsst/ch03sec02.html"/>.
</para>
</sect2>
<sect2 xml:id="sec-adm-shell-for">
<title>Creating Loops with the <command>for</command> Command</title>
<para>
The <command>for</command> 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:
</para>
<screen>for i in *.png; do
ls -l $i
done</screen>
</sect2>
</sect1>
<sect1 xml:id="sec-adm-shell-moreinfo">
<title>For More Information</title>
<para>
Important information about Bash is provided in the man pages <command>man
bash</command>. More about this topic can be found in the following list:
</para>
<itemizedlist mark="bullet" spacing="normal">
<listitem>
<para>
<link xlink:href="https://tldp.org/LDP/Bash-Beginners-Guide/html/index.html"/>—Bash
Guide for Beginners
</para>
</listitem>
<listitem>