diff --git a/Bash.md b/Bash.md index 6a41aa8e1f225f8975307db29676ab5e39ec5fbd..a32e4da9096f1a1e7e0a0ac7ed82f8a584c8dfd9 100644 --- a/Bash.md +++ b/Bash.md @@ -76,10 +76,6 @@ echo $STRING --- - - ---- - # Bash environment In a Bash shell many things constitute your environment @@ -184,6 +180,12 @@ Your first bash script: 4. make the file executable 5. run it ! +<!-- + +Durée max: 10-15 min + +--> + --- # Variables and data types in Bash @@ -228,22 +230,23 @@ myvar=$( ls ) ## Variable naming conventions -* Variable names **should start** with a letter or an underscore +- Variable names **should start** with a letter or an underscore -* Variable names can contain letters, numbers, and underscores +- Variable names can contain letters, numbers, and underscores -* Variable names are **case-sensitive** +- Variable names are **case-sensitive** -* Variable names **should not** contain spaces or **special characters** +- Variable names **should not** contain spaces or **special characters** -* Use descriptive names that reflect the purpose of the variable +- Use descriptive names that reflect the purpose of the variable -* Avoid using **reserved keywords**, such as `if`, `then`, `else`, `fi`, and so on... +- Avoid using **reserved keywords**, such as `if`, `then`, `else`, `fi`, and so on... -* **Never** name your private variables using only **UPPERCASE** characters to avoid conflicts with builtins +- **Never** name your private variables using only **UPPERCASE** characters to avoid conflicts with builtins --- +<!-- ## String manipulation Consider `string=abcABC123ABCabc` @@ -255,20 +258,21 @@ Consider `string=abcABC123ABCabc` * `${string:(-4)}` or `${string: -4}` is `Cabc` --- +--> ## String manipulation Consider `filename=/var/log/messages.tar.gz` -* substring removal from left : - * `${filename##/var}` is `/log/messages.tar.gz` -* substring removal from right : - * `${filename%%.gz}` is `/var/log/messages.tar` +- substring removal from left : + - `${filename##/var}` is `/log/messages.tar.gz` +- substring removal from right : + - `${filename%%.gz}` is `/var/log/messages.tar` You can use `*` to match all characters: -* `${filename%%.*}` is `/var/log/messages` -* `$(filename##*/)` is `messages.tar.gz` +- `${filename%%.*}` is `/var/log/messages` +- `$(filename##*/)` is `messages.tar.gz` --- @@ -340,19 +344,19 @@ echo $b # 16 # Conditional statements Use: -* `if condition; then` to start conditional block -* `else` to start alternative block -* `elif` to start alternative condition block -* `fi` to close conditional block +- `if condition; then` to start conditional block +- `else` to start alternative block +- `elif` to start alternative condition block +- `fi` to close conditional block The following operaors can be used beween conditions: -* `||` means **OR** -* `&&` mean **AND** +- `||` means **OR** +- `&&` mean **AND** --- -# Conditional exemple +# Conditional example ```bash #!/bin/bash @@ -368,6 +372,12 @@ else fi ``` +<!-- + +NOTE: réfléchir à la meilleure syntaxe à utiliser ( les ((, les [ ], les [[]] ) + +--> + --- | Operator | Description | @@ -449,12 +459,12 @@ esac # Hands-on exercise 1. In your `bash_exercises` folder create a new bash file called `exercise_2.sh` and make it executable -2. Ask the user for two numbers smaller than 100 and put them in variables `NUMBER1` and `NUMBER2` +2. Ask the user for two numbers smaller than 100 and put them in variables `number1` and `number2` > ```bash > #!/bin/bash - > read NUMBER1 - > read NUMBER2 + > read number1 + > read number2 >``` 3. Check if the numbers are smaller than 100 @@ -536,16 +546,13 @@ Useful for automating repetitive tasks Basic loop structures in Bash scripting : -* `while` : perform a set of commands while a test is true -* `until` : perform a set of commands until a test is true -* `for` : perform a set of commands for each item in a list - -* controlling loops +- `while` : perform a set of commands while a test is true +- `for` : perform a set of commands for each item in a list - * `break` : exit the currently running loop - * `continue` : stop this iteration of the loop and begin the next iteration +- controlling loops -* last loop mechanism : `select` allows you to create a simple menu system + - `break` : exit the currently running loop + - `continue` : stop this iteration of the loop and begin the next iteration --- @@ -575,7 +582,7 @@ for word in $words ``` ```bash # range with steps for loop -for value in {10..0..2} +for value in {10..0..-2} ``` ```bash # set of files @@ -620,6 +627,13 @@ done 5. Register the end time in `tend` 6. Display the total run time and the total number of letters. + +<!-- + +PY: modifier pour avoir un exemple de 10 mots directement dans le slide + +--> + --- # Arguments - Positional Parameters @@ -697,6 +711,12 @@ Shells use 3 standard I/O streams Shell has several **meta-characters** and **control operators** +<!-- + +Jerome: refaire ces 3 slides + +--> + --- # Control operators @@ -708,7 +728,8 @@ Shell has several **meta-characters** and **control operators** | `\|\|` | Execute next command only if command fails | | `&` | Don't wait for result of command before starting next command | | `\|` | Use output of command as input for the next command | -| `> file_desc` | Send stdandard output of command to file descriptor | +| `> file_desc` | Send standard output of command to file descriptor | +| `>> file_desc` | Same but in append mode | | `< file_desc` | Use content of file descriptor as input | --- @@ -751,6 +772,11 @@ done < "$input" > by default `read` removes all leading and trailing whitespace characters such as spaces and tabs <!-- + +!!!!!!!!!!!!!!!!!!!!! +REMPLACER cet exemple : a propos de l'entrée standard + + `while IFS= read -r line` The internal field separator (`IFS`) is set to the empty string to preserve whitespace issues @@ -764,10 +790,10 @@ The `-r` option is used not to allow backslashes to escape any characters Linux command returns a status when it terminates normally or abnormally -* every Linux command has an exit status -* the exit status is an integer number -* a command which exits with a **0** status has **succeeded** -* a **non-zero** (1-255) exit status indicates **failure** +- every Linux command has an exit status +- the exit status is an integer number +- a command which exits with a **0** status has **succeeded** +- a **non-zero** (1-255) exit status indicates **failure** How do I display the exit status of shell command ? @@ -797,10 +823,12 @@ command || echo "failed" command && echo "success" || echo "failed" ``` +<!-- ```bash _files="$@" [[ "$_files" == "" ]] && { echo "Usage: $0 file1.png file2.png"; exit 1; } ``` +--> <!-- Attention utilisatin du [[ ]] pas encore expliqué ? --> --- @@ -816,10 +844,10 @@ _files="$@" # Functions -* "small script within a script" that you may call multiple times -* great way to reuse code -* a function is most reuseable when it performs a single task -* good to put ancillary tasks within functions : logically separate from main code +- "small script within a script" that you may call multiple times +- great way to reuse code +- a function is most reuseable when it performs a single task +- good to put ancillary tasks within functions : logically separate from main code ```bash #!/bin/bash @@ -857,7 +885,7 @@ echo $var ``` --- - +<!-- ## Return Values Bash functions don’t allow you to return a value when called @@ -876,22 +904,11 @@ echo $? ``` --- - -Return an arbitrary value (different from a return code) from a function : -* Assign the result of the function - -```bash -my_function () { - func_result="some result" -} -my_function -echo $func_result -``` - -<!-- Note JDF: est-ce que la partie ci-dessus est utile ? Autant montrer directement la bonne manière pour moi --> -* Better way is to send the value to `stdout` using `echo` +# Return an arbitrary value from a function + +Assign the result of the function ```bash my_function () { @@ -922,15 +939,24 @@ print_something Mars # Hands-on exercise -1. Write a script called `exercise_5.sh` expecting **2 arguments**. If not exactly two arguments are provided: - * Echo an error message - * Exit with a non-zero error code +1. Write a script called `exercise_5.sh` expecting **2 arguments**. 2. Write a function taking a **folder path** (e.g `/home/ucl/elic/xxxx`) and an **extension** (e.g `py`) as arguments 3. Use the `ls` command to list the files in the given path having with the given extension. Write this list to a file called `files_found.txt`. 4. Bonus : if there are no files, Exit with a non-zero error code --- +# Subshells + +- A subshell is a "child shell" spawned by the main shell ("parent shell") +- A subshell is a **separate** instance of the command process, run as a new process +- **Unlike calling a shell script** (slide before), subshells inherit the **same** variables as the original process +- A subshell allows you to execute commands within a separate shell environment = *Subshell Sandboxing* + > useful to set temporary variables or change directories without affecting the parent shell's environment +- Subshells can be used for **parallel processing** + +--- + # Shell vs Environment Variables Consider the script `test.sh` below : @@ -950,16 +976,7 @@ bash test.sh ``` > By default, variables from the main interpreter are not available in scripts, unless you `export` them. ---- - -# Subshells - -* A subshell is a "child shell" spawned by the main shell ("parent shell") -* A subshell is a **separate** instance of the command process, run as a new process -* **Unlike calling a shell script** (slide before), subshells inherit the **same** variables as the original process -* A subshell allows you to execute commands within a separate shell environment = *Subshell Sandboxing* - > useful to set temporary variables or change directories without affecting the parent shell's environment -* Subshells can be used for **parallel processing** +<!-- --- @@ -981,15 +998,14 @@ bash -c "command1; command2; command3" > Reminder : variables in a subshell are **not** visible outside the block of code in the subshell +--> + --- ## Differences between **Sourcing** and **Executing** a script - source a script = execution **in the current shell** - > variables and functions are valid in the current shell after sourcing even if not `export`ed - - execute a script = execution in a new shell (in a subshell of the current shell) - > all new variables and functions created by the script will only live in the subshell Source a script using `source` or `.` @@ -1006,27 +1022,33 @@ source myScript.sh ```bash #!/bin/bash -COUNTRY="Belgium" +country="Belgium" greeting() { echo "You're in $1" } -greeting $COUNTRY +greeting $country ``` ```bash -COUNTRY="France" -./myScript.sh # or bash or exec -echo $COUNTRY -greeting $COUNTRY # !! +country="France" +./myScript.sh # or bash +echo $country +greeting $country # !! ``` ```bash -COUNTRY="France" +country="France" source myScript.sh -echo $COUNTRY -greeting $COUNTRY +echo $country +greeting $country ``` +<!-- + +!!!!!!!!!!!!!!!! A REDISCUTER + +--> + --- # Debug