We start with an example that can be used as a design patter to read content from a file line by line. This can be useful for example to load data in memory, validate the date then push some data to the outout using echo statement.
#!/bin/bash
while read -r line
do
echo "$line"
done < test.txt
~/bash-repl$ bash read-file.sh
This is a test
Second line
Third line
End of file
~/bash-repl$
Note: Of course someone can say this is a dump example because you can do the same thing in a single line using the "cat" builtin command. That is obviosly true but think obout the possibility here to read every line as a string then you can parse the string and dynamicly derive data from it, make validations or computations that you need to solve specific problems.
You can use file paterns with "ls" command but also with "for" loop to search files that match a specific pattern. This is like a regular expression but has different rules. I have learned several of these rules but you can dig into documentation for details.
#using pattern to list some files
pat=*[r]*e.*
echo "containing r ending with e"
echo "-------------------------"
ls -1 $pat
#using a loop
echo "-------------------------"
for file in $pat
do
echo $file
done
~/bash-repl$ bash paterns.sh
containing r ending with e
-------------------------
closure.sh
range.sh
read-file.sh
the-range.sh
-------------------------
closure.sh
range.sh
read-file.sh
the-range.sh
~/bash-repl$
We test a set of examples using just the command line in the same folder where this tutorial is located. So these are real files that we have created for this tutorial using html.
To exclude letter you can use ! or ^ in front of a letter.
>bash
bash-3.2$ ls [!bcdfghjklmnprstvxzw]*.html
arrays.html external.html index.html
bash-3.2$ ls [^bcdfghjklmnprstvxzw]*.html
arrays.html external.html index.html
bash-3.2$
Notes: In previous example we list all files that do not start with a consonant. Of course that means all files that start with anything else including special symbols or numbers or vowels. Do not forget, Linux is case sensitive.
You can use touch command to create a new empty file.
>bash
bash-3.2$ touch .test
bash-3.2$ touch .etos
bash-3.2$ ls .[t]*
.test
bash-3.2$ ls .[et]*
.etos .test
bash-3.2$
Notes: In previous example we create two files named {.test, .etos} then we list all files that start with "." having next character "e" or "t". Notce that "ls" command normally is hiding all the files starting with dot. These are usually system files.
Puting all these things together we can already create a script that is doing something more intresting. Let's list first 3 lines in all script files that start with letter "f". Study this demo and test your reading skills.
#!/bin/bash
#list script files
for fhnd in f*.sh
do
printf '_%.0s' {1..30}
echo; echo "#file: $fhnd"
i=0
# display first 3 lines
while read -r line; do
echo $line
if (( i == 3 )); then
break;
fi
(( i++ ))
done < $PWD/$fhnd
echo "..."
done
printf '=%.0s' {1..30}
echo
~/bash-repl$ bash files.sh
______________________________
#file: forxp.sh
# sequence and range
echo $(seq 0 10)
echo $(seq 1 2 20)
echo {1..20..2}
...
______________________________
#file: functions.sh
# define two functions
sum () (
echo $(( $1 + $2 ))
)
...
==============================
~/bash-repl$
Read next: Asynchronous Processes