From a117de8856be05569af5f82c0532c98a7e5fe41e Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 17:36:03 +0900 Subject: [PATCH 01/18] Create config.md --- _extras/config.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 _extras/config.md diff --git a/_extras/config.md b/_extras/config.md new file mode 100644 index 0000000..ec6058a --- /dev/null +++ b/_extras/config.md @@ -0,0 +1,66 @@ +# Bash Configurations Demystified +.bash_profile, .profile, & .bashrc Conventions + +Bash configurations on Linux and OS X can be confusing for many people, myself included. I've written this short guide to remind you and I both of a reasonable set of conventions you could follow. +Login Shell vs. Non-login Shell + +When logging in via the console (e.g., an SSH session, the scary console login after you've messed up your GUI settings, etc.), you are starting a login shell. If you open a terminal application (e.g. xterm, etc.) from your desktop, then you are starting a non-login shell (except on OS X, discussed later). +Linux (Ubuntu specifically) + +On a clean install of Ubuntu, you'll notice your home directory contains both a .profile and .bashrc file. Starting a login shell executes .profile and starting a non-login shell executes .bashrc. Notice that inside .profile you'll find +``` +# if running bash +if [ -n "$BASH_VERSION" ]; then + # include .bashrc if it exists + if [ -f "$HOME/.bashrc" ]; then + . "$HOME/.bashrc" + fi +fi +``` +This means that login shells execute .profile and then source .bashrc, while non-login shells execute .bashrc only. + +![](assets/ubuntu_bash_diagram.png) + +Be Aware (if you add a .bash_profile) + +You should also be aware that to start a login shell bash looks for .bash_profile, .bash_login, and .profile in that order and it only reads and executes the first one it finds. By default, the first two are not present on Ubuntu. Programs like RVM add a .bash_profile file so you should be sure to append + + [[ -s ${HOME}/.profile ]] && source ${HOME}/.profile + +to the added .bash_profile file. (After installing RVM you might have noticed that ls colorization disappeared from login shells as a result of .bashrc no longer being sourced since .profile was ignored; this should resolve those issues). Sourcing .profile means that now, every time you start a login shell .bash_profile is executed, then .profile, and finally .bashrc. Starting a non-login shell will just execute .bashrc as before. +Mac OS X + +On a clean install of OS X, you should have a .bashrc file and a .bash_profile file. Unlike most of the Unix/Linux world, OS X terminal applications (e.g. Terminal, iTerm2, etc.) start a login shell. So whether you SSH into an OS X machine or launch a terminal application, bash will launch as a login shell. While Ubuntu makes use of .profile by default, OS X chose to use .bash_profile (and no .profile file), which takes precedence on the list given above. Inside the .bash_profile on OS X, you'll find something like + + [[ -s ~/.bashrc ]] && source ~/.bashrc + +Just as Ubuntu's .profile sourced .bashrc, OS X's .bash_profile sources .bashrc too. On OS X, whether you login via a GUI and open a terminal application, SSH in, or login at a console, you'll be starting a login shell which will execute .bash_profile and then source .bashrc. + +![](os_x_bash_diagram.png) + +## Where do I make changes? + +Whether you use Linux or OS X, any bash-related changes, such as adding aliases, functions, or tweaking the prompt appearance can be appended to .bashrc. If you've set up sourcing as described above, .bashrc is executed in both login and non-login shells on both Linux and Mac OS X. + +Another related option is to append + + [[ -s ${HOME}/.local.bash ]] && source ${HOME}/.local.bash + +to .bashrc and then make all further bash customization changes to .local.bash. This seems to be common on company issued machines since admins don't like users mucking around with .bashrc. If this is the case for you, then make your bash config changes to .local.bash. +When NOT to modify .bashrc? + +As the name implies, .bashrc is for bash configs. Environment variables or other configuration settings should typically be written to .profile on Ubuntu and .bash_profile on OS X. A common desire is to extend the PATH variable: + +```` +# Add path to Python scripts directory +PATH=/usr/local/share/python:$PATH +```` + +On Linux, you would append this path extension to your .profile, unless you've set up a .bash_profile that sources .profile which then sources .bashrc (just choose a strategy and be consistent). Logging into your machine again, every terminal session will have the PATH you defined. This happens because .profile (or .bash_profile) is executed at login, before any non-login shells are started. I do most of my PATH modifications when first configuring a machine, so it is no problem to apply changes at the next login. If you need to apply your change now, in your current non-login shell, you could: + + source ~/.profile # or ~/.bash_profile + +On OS X, you should add the line to .bash_profile, although you could optionally set up .bash_profile to source .profile and .bashrc for symetry with Ubuntu and put the line in .profile. +Errors + +If you find any errors or have any suggestions, please kindly contact me at @dghubble or by email at dghubble@gmail.com. I'll keep this updated reference. From 48331429e7a9c6e975db6f62925e0d42d8bb412d Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 17:37:14 +0900 Subject: [PATCH 02/18] Create README.md --- _extras/assets/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 _extras/assets/README.md diff --git a/_extras/assets/README.md b/_extras/assets/README.md new file mode 100644 index 0000000..3772213 --- /dev/null +++ b/_extras/assets/README.md @@ -0,0 +1 @@ +Folder for images, etc. From f87db7181879f14b6839979bd126d066c484c2b8 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 17:40:21 +0900 Subject: [PATCH 03/18] Add files via upload --- _extras/assets/bash-config - osx.png | Bin 0 -> 30591 bytes _extras/assets/bash-config-ubuntu.png | Bin 0 -> 42254 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 _extras/assets/bash-config - osx.png create mode 100644 _extras/assets/bash-config-ubuntu.png diff --git a/_extras/assets/bash-config - osx.png b/_extras/assets/bash-config - osx.png new file mode 100644 index 0000000000000000000000000000000000000000..c3d32502d46fb74911b93ecc2626c8ede9fabf9f GIT binary patch literal 30591 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 literal 0 HcmV?d00001 diff --git a/_extras/assets/bash-config-ubuntu.png b/_extras/assets/bash-config-ubuntu.png new file mode 100644 index 0000000000000000000000000000000000000000..dd20b16c0bec49217d6ecec93b3108f652233a96 GIT binary patch literal 42254 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 Date: Fri, 19 Apr 2024 17:43:40 +0900 Subject: [PATCH 04/18] add help in _extras --- _extras/help.md | 285 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 _extras/help.md diff --git a/_extras/help.md b/_extras/help.md new file mode 100644 index 0000000..9c46bef --- /dev/null +++ b/_extras/help.md @@ -0,0 +1,285 @@ +# How to add a help message to shell script + +## About functions + +Shell functions are lists of Bash program statements that are stored in the shell's environment and can be executed, like any other command, by typing their name at the command line. Shell functions may also be known as procedures or subroutines, depending upon which other programming language you are using. + +Functions are called in scripts or from the command-line interface (CLI) by using their names, just as you would for any other command. In a CLI program or a script, the commands in the function execute when they are called, then the program flow sequence returns to the calling entity, and the next series of program statements in that entity executes. + +The syntax of a function is: + + FunctionName(){program statements} + +Explore this by creating a simple function at the CLI. (The function is stored in the shell environment for the shell instance in which it is created.) You are going to create a function called hw, which stands for "hello world." Enter the following code at the CLI and press Enter. Then enter hw as you would any other shell command: + +``` +[student@testvm1 ~]$ hw(){ echo "Hi there kiddo"; } +[student@testvm1 ~]$ hw +Hi there kiddo +[student@testvm1 ~]$About functions +``` + +Shell functions are lists of Bash program statements that are stored in the shell's environment and can be executed, like any other command, by typing their name at the command line. Shell functions may also be known as procedures or subroutines, depending upon which other programming language you are using. + +Functions are called in scripts or from the command-line interface (CLI) by using their names, just as you would for any other command. In a CLI program or a script, the commands in the function execute when they are called, then the program flow sequence returns to the calling entity, and the next series of program statements in that entity executes. + +The syntax of a function is: + + FunctionName(){program statements} + +Explore this by creating a simple function at the CLI. (The function is stored in the shell environment for the shell instance in which it is created.) You are going to create a function called hw, which stands for "hello world." Enter the following code at the CLI and press Enter. Then enter hw as you would any other shell command: + +``` +[student@testvm1 ~]$ hw(){ echo "Hi there kiddo"; } +[student@testvm1 ~]$ hw +Hi there kiddo +[student@testvm1 ~]$ +``` + +OK, so I am a little tired of the standard "Hello world" starter. Now, list all of the currently defined functions. There are a lot of them, so I am showing just the new hw function. When it is called from the command line or within a program, a function performs its programmed task and then exits and returns control to the calling entity, the command line, or the next Bash program statement in a script after the calling statement: + +``` +[student@testvm1 ~]$ declare -f | less + +hw () +{ + echo "Hi there kiddo" +} + +``` + +Remove that function because you do not need it anymore. You can do that with the unset command: + +``` +[student@testvm1 ~]$ unset -f hw ; hw +bash: hw: command not found +[student@testvm1 ~]$ +``` + +## Creating the Help function + +Open the hello program in an editor and add the Help function below to the hello program code after the copyright statement but before the echo "Hello world!" statement. This Help function will display a short description of the program, a syntax diagram, and short descriptions of the available options. Add a call to the Help function to test it and some comment lines that provide a visual demarcation between the functions and the main portion of the program: + +``` +################################################################################ +# Help # +################################################################################ +Help() +{ + # Display Help + echo "Add description of the script functions here." + echo + echo "Syntax: scriptTemplate [-g|h|v|V]" + echo "options:" + echo "g Print the GPL license notification." + echo "h Print this Help." + echo "v Verbose mode." + echo "V Print software version and exit." + echo +} + +################################################################################ +################################################################################ +# Main program # +################################################################################ +################################################################################ + +Help +echo "Hello world!" + +The options described in this Help function are typical for the programs I write, although none are in the code yet. Run the program to test it: + +[student@testvm1 ~]$ ./hello +Add description of the script functions here. + +Syntax: scriptTemplate [-g|h|v|V] +options: +g Print the GPL license notification. +h Print this Help. +v Verbose mode. +V Print software version and exit. + +Hello world! +[student@testvm1 ~]$ +``` + +Because you have not added any logic to display Help only when you need it, the program will always display the Help. Since the function is working correctly, read on to add some logic to display the Help only when the -h option is used when you invoke the program at the command line. + +## Handling options + +A Bash script's ability to handle command-line options such as -h gives some powerful capabilities to direct the program and modify what it does. In the case of the -h option, you want the program to print the Help text to the terminal session and then quit without running the rest of the program. The ability to process options entered at the command line can be added to the Bash script using the while command (see How to program with Bash: Loops to learn more about while) in conjunction with the getops and case commands. + +The getops command reads any and all options specified at the command line and creates a list of those options. In the code below, the while command loops through the list of options by setting the variable $options for each. The case statement is used to evaluate each option in turn and execute the statements in the corresponding stanza. The while statement will continue to evaluate the list of options until they have all been processed or it encounters an exit statement, which terminates the program. + +Be sure to delete the Help function call just before the echo "Hello world!" statement so that the main body of the program now looks like this: +``` +################################################################################ +################################################################################ +# Main program # +################################################################################ +################################################################################ +################################################################################ +# Process the input options. Add options as needed. # +################################################################################ +# Get the options +while getopts ":h" option; do + case $option in + h) # display Help + Help + exit;; + esac +done + +echo "Hello world!" +``` + +Notice the double semicolon at the end of the exit statement in the case option for -h. This is required for each option added to this case statement to delineate the end of each option. + +## Testing + +Testing is now a little more complex. You need to test your program with a number of different options—and no options—to see how it responds. First, test with no options to ensure that it prints "Hello world!" as it should: + +``` +[student@testvm1 ~]$ ./hello +Hello world! +``` + +That works, so now test the logic that displays the Help text: + +``` +[student@testvm1 ~]$ ./hello -h +Add description of the script functions here. + +Syntax: scriptTemplate [-g|h|t|v|V] +options: +g Print the GPL license notification. +h Print this Help. +v Verbose mode. +V Print software version and exit. +``` + +That works as expected, so try some testing to see what happens when you enter some unexpected options: + +``` +[student@testvm1 ~]$ ./hello -x +Hello world! +[student@testvm1 ~]$ ./hello -q +Hello world! +[student@testvm1 ~]$ ./hello -lkjsahdf +Add description of the script functions here. + +Syntax: scriptTemplate [-g|h|t|v|V] +options: +g Print the GPL license notification. +h Print this Help. +v Verbose mode. +V Print software version and exit. + +[student@testvm1 ~]$ +``` + +The program just ignores any options without specific responses without generating any errors. But notice the last entry (with -lkjsahdf for options): because there is an h in the list of options, the program recognizes it and prints the Help text. This testing has shown that the program doesn't have the ability to handle incorrect input and terminate the program if any is detected. + +You can add another case stanza to the case statement to match any option that doesn't have an explicit match. This general case will match anything you have not provided a specific match for. The case statement now looks like this, with the catch-all match of \? as the last case. Any additional specific cases must precede this final one: + +``` +while getopts ":h" option; do + case $option in + h) # display Help + Help + exit;; + \?) # incorrect option + echo "Error: Invalid option" + exit;; + esac +done +``` + +Test the program again using the same options as before and see how it works now. + +## Where you are + +You have accomplished a good amount in this article by adding the capability to process command-line options and a Help procedure. Your Bash script now looks like this: + +``` +#!/usr/bin/bash +################################################################################ +# scriptTemplate # +# # +# Use this template as the beginning of a new program. Place a short # +# description of the script here. # +# # +# Change History # +# 11/11/2019 David Both Original code. This is a template for creating # +# new Bash shell scripts. # +# Add new history entries as needed. # +# # +# # +################################################################################ +################################################################################ +################################################################################ +# # +# Copyright (C) 2007, 2019 David Both # +# LinuxGeek46@both.org # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +################################################################################ +################################################################################ +################################################################################ + +################################################################################ +# Help # +################################################################################ +Help() +{ + # Display Help + echo "Add description of the script functions here." + echo + echo "Syntax: scriptTemplate [-g|h|t|v|V]" + echo "options:" + echo "g Print the GPL license notification." + echo "h Print this Help." + echo "v Verbose mode." + echo "V Print software version and exit." + echo +} + +################################################################################ +################################################################################ +# Main program # +################################################################################ +################################################################################ +################################################################################ +# Process the input options. Add options as needed. # +################################################################################ +# Get the options +while getopts ":h" option; do + case $option in + h) # display Help + Help + exit;; + \?) # incorrect option + echo "Error: Invalid option" + exit;; + esac +done + +echo "Hello world!" +``` +Be sure to test this version of the program very thoroughly. Use random inputs and see what happens. You should also try testing valid and invalid options without using the dash (-) in front. + + +Source: https://opensource.com/article/19/12/help-bash-program \ No newline at end of file From 970406e4e71e737741586e975a9d0764f4acac3a Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 17:55:21 +0900 Subject: [PATCH 05/18] update awk, remove dir, etc. --- _episodes/03-file-transfer.md | 1 - ...cture.md => 05-directory-structure.md.bak} | 0 _episodes/09-commandsubstitution.md | 14 ++++++------- _episodes/{10_awk.md => 10-awk.md} | 21 ++++++++++--------- 4 files changed, 18 insertions(+), 18 deletions(-) rename _episodes/{05-directory-structure.md => 05-directory-structure.md.bak} (100%) rename _episodes/{10_awk.md => 10-awk.md} (88%) diff --git a/_episodes/03-file-transfer.md b/_episodes/03-file-transfer.md index 7f65865..a2dd3f8 100644 --- a/_episodes/03-file-transfer.md +++ b/_episodes/03-file-transfer.md @@ -1,4 +1,3 @@ - --- title: "Transferring Files" teaching: 10 diff --git a/_episodes/05-directory-structure.md b/_episodes/05-directory-structure.md.bak similarity index 100% rename from _episodes/05-directory-structure.md rename to _episodes/05-directory-structure.md.bak diff --git a/_episodes/09-commandsubstitution.md b/_episodes/09-commandsubstitution.md index 9e3b1ca..757ee40 100644 --- a/_episodes/09-commandsubstitution.md +++ b/_episodes/09-commandsubstitution.md @@ -1,14 +1,14 @@ --- layout: page -title: The Unix Shell -subtitle: Command Subsitution +title: Command Subsitution +questions: +- "How to use command substitutions for arguments flexibility?" minutes: 15 +objectives: +- Understand the need for flexibility regarding arguments +- Generate the values of the arguments on the fly using command substitution +- Understand the difference between pipes/redirection, and the command substitution operator --- -> ## Learning Objectives {.objectives} -> -> * Understand the need for flexibility regarding arguments -> * Generate the values of the arguments on the fly using command substitution -> * Understand the difference between pipes/redirection, and the command substitution operator ## Introduction diff --git a/_episodes/10_awk.md b/_episodes/10-awk.md similarity index 88% rename from _episodes/10_awk.md rename to _episodes/10-awk.md index 9671e21..dd7c0cf 100644 --- a/_episodes/10_awk.md +++ b/_episodes/10-awk.md @@ -2,18 +2,19 @@ layout: page title: AWK subtitle: Manipulating and filtering complex data +quesstions: +- "How to use AWK for text processing?" minutes: 120 +objectives: + - Explain why AWK is useful and when it is better than pipes. + - Show a basic usage similar to the command "cut" + - Introduce the filed separator parameter. + - Use regulax expressions to perform different instructions. + - Introduce BEGIN and END keywords. + - Use the if then structure to change behaviour for the same matching regex. + - Introduce the array data structure. + - Use the for loop to cycle through an array --- -> ## Learning Objectives {.objectives} -> -> * Explain why AWK is useful and when it is better than pipes. -> * Show a basic usage similar to the command "cut" -> * Introduce the filed separator parameter. -> * Use regulax expressions to perform different instructions. -> * Introduce BEGIN and END keywords. -> * Use the if then structure to change behaviour for the same matching regex. -> * Introduce the array data structure. -> * Use the for loop to cycle through an array Prerequisite: shell and any programming language From 8fc6037fb6f71241c3b2fbb3ea92ead549f82ac8 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 18:13:06 +0900 Subject: [PATCH 06/18] update ch 9 and 10 --- _episodes/09-commandsubstitution.md | 3 +-- _episodes/10-awk.md | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/_episodes/09-commandsubstitution.md b/_episodes/09-commandsubstitution.md index 757ee40..7b741be 100644 --- a/_episodes/09-commandsubstitution.md +++ b/_episodes/09-commandsubstitution.md @@ -1,9 +1,8 @@ --- -layout: page title: Command Subsitution +teaching: 10 questions: - "How to use command substitutions for arguments flexibility?" -minutes: 15 objectives: - Understand the need for flexibility regarding arguments - Generate the values of the arguments on the fly using command substitution diff --git a/_episodes/10-awk.md b/_episodes/10-awk.md index dd7c0cf..eabe296 100644 --- a/_episodes/10-awk.md +++ b/_episodes/10-awk.md @@ -1,19 +1,19 @@ --- -layout: page title: AWK subtitle: Manipulating and filtering complex data +teaching: 20 +exercise: 5 quesstions: - "How to use AWK for text processing?" -minutes: 120 objectives: - - Explain why AWK is useful and when it is better than pipes. - - Show a basic usage similar to the command "cut" - - Introduce the filed separator parameter. - - Use regulax expressions to perform different instructions. - - Introduce BEGIN and END keywords. - - Use the if then structure to change behaviour for the same matching regex. - - Introduce the array data structure. - - Use the for loop to cycle through an array +- "Explain why AWK is useful and when it is better than pipes" +- "Show a basic usage similar to the command "cut" " +- "Introduce the filed separator parameter" +- "Use regulax expressions to perform different instructions" +- "Introduce BEGIN and END keywords" +- "Use the if then structure to change behaviour for the same matching regex" +- "Introduce the array data structure" +- "Use the for loop to cycle through an array" --- Prerequisite: shell and any programming language From 383f1e5cb74c867d9c6a7526cf16fd695db00829 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 18:23:40 +0900 Subject: [PATCH 07/18] update ch 9 and 10 again to show overview --- _episodes/09-commandsubstitution.md | 1 + _episodes/10-awk.md | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/_episodes/09-commandsubstitution.md b/_episodes/09-commandsubstitution.md index 7b741be..1e2dda5 100644 --- a/_episodes/09-commandsubstitution.md +++ b/_episodes/09-commandsubstitution.md @@ -1,6 +1,7 @@ --- title: Command Subsitution teaching: 10 +excercise: 5 questions: - "How to use command substitutions for arguments flexibility?" objectives: diff --git a/_episodes/10-awk.md b/_episodes/10-awk.md index eabe296..8c0e45f 100644 --- a/_episodes/10-awk.md +++ b/_episodes/10-awk.md @@ -1,6 +1,5 @@ --- title: AWK -subtitle: Manipulating and filtering complex data teaching: 20 exercise: 5 quesstions: @@ -16,7 +15,9 @@ objectives: - "Use the for loop to cycle through an array" --- -Prerequisite: shell and any programming language +AWK is a tool for manipulating and filtering complex data. This chapter requires understanding of previous shell chapters and any programming language. + +Let's start. If we need to count the number of lines in a file, we can use the previously showed command for word counting wc From f36af6365194d9b8ca35fe5af8f43dffe6566d90 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 18:31:09 +0900 Subject: [PATCH 08/18] rename md files due to remove ch dir structure --- _episodes/{06-job-control.md => 05-job-control.md} | 0 _episodes/{07-aliases.md => 06-aliases.md} | 0 ...{08-environment-variables.md => 07-environment-variables.md} | 0 .../{09-commandsubstitution.md => 08-command-substitution.md} | 0 _episodes/{10-awk.md => 09-awk.md} | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) rename _episodes/{06-job-control.md => 05-job-control.md} (100%) rename _episodes/{07-aliases.md => 06-aliases.md} (100%) rename _episodes/{08-environment-variables.md => 07-environment-variables.md} (100%) rename _episodes/{09-commandsubstitution.md => 08-command-substitution.md} (100%) rename _episodes/{10-awk.md => 09-awk.md} (99%) diff --git a/_episodes/06-job-control.md b/_episodes/05-job-control.md similarity index 100% rename from _episodes/06-job-control.md rename to _episodes/05-job-control.md diff --git a/_episodes/07-aliases.md b/_episodes/06-aliases.md similarity index 100% rename from _episodes/07-aliases.md rename to _episodes/06-aliases.md diff --git a/_episodes/08-environment-variables.md b/_episodes/07-environment-variables.md similarity index 100% rename from _episodes/08-environment-variables.md rename to _episodes/07-environment-variables.md diff --git a/_episodes/09-commandsubstitution.md b/_episodes/08-command-substitution.md similarity index 100% rename from _episodes/09-commandsubstitution.md rename to _episodes/08-command-substitution.md diff --git a/_episodes/10-awk.md b/_episodes/09-awk.md similarity index 99% rename from _episodes/10-awk.md rename to _episodes/09-awk.md index 8c0e45f..aeb9a69 100644 --- a/_episodes/10-awk.md +++ b/_episodes/09-awk.md @@ -2,7 +2,7 @@ title: AWK teaching: 20 exercise: 5 -quesstions: +questions: - "How to use AWK for text processing?" objectives: - "Explain why AWK is useful and when it is better than pipes" From b2478f552e5b5ca233a4e4131dc2191b771a9467 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 18:55:54 +0900 Subject: [PATCH 09/18] rm lesson 5 --- _episodes/05-directory-structure.md.bak | 17 ----------------- _episodes/08-command-substitution.md | 4 ++-- _episodes/09-awk.md | 6 +++--- 3 files changed, 5 insertions(+), 22 deletions(-) delete mode 100644 _episodes/05-directory-structure.md.bak diff --git a/_episodes/05-directory-structure.md.bak b/_episodes/05-directory-structure.md.bak deleted file mode 100644 index cee67e4..0000000 --- a/_episodes/05-directory-structure.md.bak +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Directory structure -teaching: 5 -exercises: 0 -questions: -- "Understanding the concept of Unix directory structure" -objectives: -- "FIXME" -keypoints: -- "FIXME" ---- - -All Unix files are integrated in a single directory structure. The file-system is arranged in a structure like an inverted tree. The top of this tree is the root and is written as a slash ‘/’. - -## The `tree` command - -FIXME diff --git a/_episodes/08-command-substitution.md b/_episodes/08-command-substitution.md index 1e2dda5..3695098 100644 --- a/_episodes/08-command-substitution.md +++ b/_episodes/08-command-substitution.md @@ -1,7 +1,7 @@ --- -title: Command Subsitution +title: "Command Subsitution" teaching: 10 -excercise: 5 +excercises: 5 questions: - "How to use command substitutions for arguments flexibility?" objectives: diff --git a/_episodes/09-awk.md b/_episodes/09-awk.md index aeb9a69..1af7a3c 100644 --- a/_episodes/09-awk.md +++ b/_episodes/09-awk.md @@ -1,7 +1,7 @@ --- -title: AWK +title: "AWK" teaching: 20 -exercise: 5 +exercises: 5 questions: - "How to use AWK for text processing?" objectives: @@ -15,7 +15,7 @@ objectives: - "Use the for loop to cycle through an array" --- -AWK is a tool for manipulating and filtering complex data. This chapter requires understanding of previous shell chapters and any programming language. +AWK is a tool for manipulating and filtering complex data. It stands for Aho, Weinberger, and Kernighan, the designers of this prgoram. This chapter requires understanding of previous shell lessons and any programming language. Let's start. From 194eaeb6eccc3a5d4484974ea621e2dd66344b73 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 19:14:20 +0900 Subject: [PATCH 10/18] update lesson titles --- _episodes/05-job-control.md | 2 +- _episodes/06-aliases.md | 2 +- _episodes/08-command-substitution.md | 10 +++++----- _episodes/09-awk.md | 10 ++++++---- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/_episodes/05-job-control.md b/_episodes/05-job-control.md index da3beba..7330f39 100644 --- a/_episodes/05-job-control.md +++ b/_episodes/05-job-control.md @@ -1,5 +1,5 @@ --- -title: Job control +title: Job Control teaching: 5 exercises: 0 questions: diff --git a/_episodes/06-aliases.md b/_episodes/06-aliases.md index 8915182..27451ef 100644 --- a/_episodes/06-aliases.md +++ b/_episodes/06-aliases.md @@ -1,5 +1,5 @@ --- -title: Aliases and bash customization +title: Aliases and Bash Customization teaching: 10 minutes exercises: 0 questions: diff --git a/_episodes/08-command-substitution.md b/_episodes/08-command-substitution.md index 3695098..bd9d835 100644 --- a/_episodes/08-command-substitution.md +++ b/_episodes/08-command-substitution.md @@ -39,7 +39,7 @@ $ for cutoff in 0.001 0.01 0.05; do In the second example, the things to loop over: `"0.001 0.01 0.05"` are spelled out by you. -## Looping over the words in a string {.callout} +## Looping over the words in a string > > In the previous example you can make your code neater and self-documenting by putting the cutoff values > in a separate string: @@ -173,7 +173,7 @@ output works best within single commands and whitespace- or newline-separated words works best for lists over which to iterate in loops. -> ## Generating filenames based on a timestamp {.challenge} +> ## Generating filenames based on a timestamp > > It can be useful to create the filename 'on the fly'. For instance, if > some program called `qualitycontrol` is run periodically (or @@ -204,10 +204,9 @@ loops. > few times, waiting a few seconds between invocations (use the arrow-up > key to avoid having to retype the command) +{: .challenge} - -## Juggling filename extensions {.challenge} - +> ## Juggling filename extensions > When running an analysis program with a certain input file, it > is often required that the output has the same name as the input, but with > a different filename extension, e.g. @@ -237,6 +236,7 @@ loops. > ~~~ > but for *each* of the `.pdb`-files. +{: .challenge} ## Closing remarks diff --git a/_episodes/09-awk.md b/_episodes/09-awk.md index 1af7a3c..63a23ed 100644 --- a/_episodes/09-awk.md +++ b/_episodes/09-awk.md @@ -1,5 +1,5 @@ --- -title: "AWK" +title: AWK teaching: 20 exercises: 5 questions: @@ -8,7 +8,7 @@ objectives: - "Explain why AWK is useful and when it is better than pipes" - "Show a basic usage similar to the command "cut" " - "Introduce the filed separator parameter" -- "Use regulax expressions to perform different instructions" +- "Use regular expressions to perform different instructions" - "Introduce BEGIN and END keywords" - "Use the if then structure to change behaviour for the same matching regex" - "Introduce the array data structure" @@ -94,9 +94,10 @@ Since NF is the number of the last field, $NF contains its value. $ awk '{print "This line has",NF,"columns. The last one contains",$NF}' example.txt ~~~ -> ## Field separator {.callout} +> ## Field separator > Out there we have different file formats: our data may be comma separated (csv), > tab separated (tsv), by semicolon or by any other character. +{: .callout} To specify the field separator, we should provide it at command line like: @@ -108,8 +109,9 @@ In this case , we are printing the second field in each line, using comma as sep Please notice that the character space is now part of the field value, since it is no longer the separator. -> ## Matching lines {.callout} +> ## Matching lines > Maybe we would like to perform different instruction on different lines. +{: .callout} Awk allows you to specify a matching pattern, like the command grep does. From fd6ffb3548ad65255f43ae1133117940fbf341fd Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 19:17:57 +0900 Subject: [PATCH 11/18] fix typo in lesson 8 -> excercise --- _episodes/08-command-substitution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_episodes/08-command-substitution.md b/_episodes/08-command-substitution.md index bd9d835..b5533d0 100644 --- a/_episodes/08-command-substitution.md +++ b/_episodes/08-command-substitution.md @@ -1,7 +1,7 @@ --- title: "Command Subsitution" teaching: 10 -excercises: 5 +exercises: 5 questions: - "How to use command substitutions for arguments flexibility?" objectives: From a33667ce62078440c4c51ca3c42c96e298dd12b4 Mon Sep 17 00:00:00 2001 From: b-atmaja Date: Fri, 19 Apr 2024 21:57:26 +0900 Subject: [PATCH 12/18] update lessons 8-9 --- _episodes/08-command-substitution.md | 19 ++++++++----------- _episodes/09-awk.md | 3 ++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/_episodes/08-command-substitution.md b/_episodes/08-command-substitution.md index b5533d0..47788da 100644 --- a/_episodes/08-command-substitution.md +++ b/_episodes/08-command-substitution.md @@ -1,5 +1,5 @@ --- -title: "Command Subsitution" +title: "Command Substitution" teaching: 10 exercises: 5 questions: @@ -56,10 +56,9 @@ However, you don't always know in advance *what* you have to loop over. It could well be that it is not a simple file name pattern (in which case you can use wildcards), or that it is not a small, known set of values (in which case you can write them out explicitly as was done -in the second example). It would therefore be nice if you could loop +in the second example). It would, therefore be nice if you could loop over filenames or over words contained in a file. Suppose that file -`cohort2010.txt` contains the filenames over which to iterate, then it -would be nice to able to say something like: +`cohort2010.txt` contains the filenames over which to iterate; then it would be nice to able to say something like: ~~~ # (imaginary syntax) @@ -73,7 +72,7 @@ $ for file in [INSERT THE CONTENTS OF cohort2010.txt HERE] This would be more general, more flexible and more tractable than relying on the wildcard mechanism. What we need, therefore, is a -mechanism that actually replaces everytying beween `[` and `]` with the +mechanism that actually replaces everything between `[` and `]` with the desired names of input files, just before the loop starts. Thankfully, this mechanism exists, and it is called the **command substitution operator** (previously written using the **backtick operator**). It looks much like the previous snippet: @@ -96,7 +95,7 @@ replaced with simple spaces. In legacy code, you may see the same construct but with a different syntax. It starts and ends with backticks, `` ` `` (not to be confused with the single quote `'` !). The backticks work exactly the -same as the command substitution done by `$(` and `)`. However its use +same as the command substitution done by `$(` and `)`. However, its use is discouraged as backticks cannot be nested. ## Example @@ -170,7 +169,7 @@ whitespace to separate command, options (flags) and parameters / arguments. For the same reason it is essential that the command (or pipeline) inside the backticks produces *clean* output: single word output works best within single commands and whitespace- or -newline-separated words works best for lists over which to iterate in +newline-separated words work best for lists over which to iterate in loops. > ## Generating filenames based on a timestamp @@ -239,12 +238,10 @@ loops. {: .challenge} ## Closing remarks - -The command subsitution operator provides us with a +The command substitution operator provides us with a powerful new piece of 'plumbing' that allows us to connect "small pieces, loosely together" to keep with the Unix philosophy. It is remotely similar to the `|` operator in the sense that it connects two programs. But there is also a clear difference: `|` connects the standard output of one command to the standard input of another command, -where as `` $(command) `` is substituted 'in-place' into the the shell -script, and always provides parameters, options, arguments to other commands. +where as `` $(command) `` is substituted 'in-place' into the shell script, and always provides parameters, options, and arguments to other commands. diff --git a/_episodes/09-awk.md b/_episodes/09-awk.md index 63a23ed..3eef8fd 100644 --- a/_episodes/09-awk.md +++ b/_episodes/09-awk.md @@ -1,9 +1,10 @@ --- +layout: page title: AWK teaching: 20 exercises: 5 questions: -- "How to use AWK for text processing?" +- "How to use AWK for text processing?" objectives: - "Explain why AWK is useful and when it is better than pipes" - "Show a basic usage similar to the command "cut" " From 3d3aef4093c04eff3b2d992dfb437b74ac03fb31 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Fri, 19 Apr 2024 23:57:51 +0900 Subject: [PATCH 13/18] Update 09-awk.md --- _episodes/09-awk.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/_episodes/09-awk.md b/_episodes/09-awk.md index 3eef8fd..73a464c 100644 --- a/_episodes/09-awk.md +++ b/_episodes/09-awk.md @@ -1,5 +1,4 @@ --- -layout: page title: AWK teaching: 20 exercises: 5 @@ -7,11 +6,11 @@ questions: - "How to use AWK for text processing?" objectives: - "Explain why AWK is useful and when it is better than pipes" -- "Show a basic usage similar to the command "cut" " +- "Show a basic usage similar to the command `cat` command" - "Introduce the filed separator parameter" - "Use regular expressions to perform different instructions" - "Introduce BEGIN and END keywords" -- "Use the if then structure to change behaviour for the same matching regex" +- "Use the `if-then` structure to change behaviour for the same matching regex" - "Introduce the array data structure" - "Use the for loop to cycle through an array" --- @@ -30,7 +29,7 @@ $ wc -l example.txt As you probably remember, -l is an option that asks for the number of lines only. However, wc counts the number of newlines in the file, if the last line does -not contain a carriage return (i.e. there is no emptyline at the end of the file), +not contain a carriage return (i.e. there is no empty line at the end of the file), the result is going be the actual number of lines minus one. A workaround is to use Awk. Awk is command line program that takes as input a set @@ -45,7 +44,7 @@ Example: $ awk '{print $0}' example.txt ~~~ -This command has the same output of "cat": it prints each line from the example.txt +This command has the same output as `cat`: it prints each line from the example.txt file. The structure of the instruction is the following: @@ -97,21 +96,21 @@ $ awk '{print "This line has",NF,"columns. The last one contains",$NF}' example. > ## Field separator > Out there we have different file formats: our data may be comma separated (csv), -> tab separated (tsv), by semicolon or by any other character. +> tab separated (tsv), by a semicolon or by any other character. {: .callout} -To specify the field separator, we should provide it at command line like: +To specify the field separator, we should provide it at the command line like: ~~~ {.bash} $ awk -F "," '{print $2}' example2.txt ~~~ -In this case , we are printing the second field in each line, using comma as separator. +In this case, we are printing the second field in each line, using comma as separator. Please notice that the character space is now part of the field value, since it is no longer the separator. > ## Matching lines -> Maybe we would like to perform different instruction on different lines. +> Maybe we would like to perform different instructions on different lines. {: .callout} Awk allows you to specify a matching pattern, like the command grep does. @@ -122,7 +121,7 @@ Let's look at the file content $ awk '{print $0}' example.pdb ~~~ -It seems an abriged PDB file. If we would like to print only lines starting with the word +It seems to be an abridged PDB file. If we would like to print only lines starting with the word "ATOM", we type: ~~~ {.bash} @@ -132,7 +131,7 @@ awk '/^ATOM/ {print $0}' example.pdb In this case, we specify the pattern before the instructions: only lines starting with the text "ATOM". As you remember, ^ means "at the beginning of the line". -We can specify more that one pattern: +We can specify more than one pattern: ~~~ {.bash} awk '/^ATOM/ {print $7,$8,$9} /^HEADER/ {print $NF}' example.pdb From e64a233ba1313d5ec68992e452f0f278185947c9 Mon Sep 17 00:00:00 2001 From: bagustris Date: Sun, 21 Apr 2024 23:17:25 +0900 Subject: [PATCH 14/18] fix missing keypoints --- _episodes/03-file-transfer.md | 10 ++++++---- _episodes/08-command-substitution.md | 25 +++++++++++++++---------- _episodes/09-awk.md | 7 ++++--- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/_episodes/03-file-transfer.md b/_episodes/03-file-transfer.md index a2dd3f8..dfb18bd 100644 --- a/_episodes/03-file-transfer.md +++ b/_episodes/03-file-transfer.md @@ -3,11 +3,13 @@ title: "Transferring Files" teaching: 10 exercises: 0 questions: -- "How to use wget, curl and lftp to transfer file?" +- "How to use wget, curl, and lftp to transfer files?" objectives: -- "FIXME" +- "To know different ways to interact with remote files" keypoints: -- "FIXME" +- "`wget` is the default tool, available in most Linux, to download file." +- "`curl` is another tools to download file which support larger protocols." +- "`lftp` is sosphisticated file transfer program with more capability including torrent support." --- There are other ways to interact with remote files other than git. @@ -93,7 +95,7 @@ where: `-m` is for mirroring with time stamping, infinite recursion depth, and preservation of FTP directory settings `-k` converts links to make them suitable for local viewing -`-q` supresses the output to the screen +`-q` suppresses the output to the screen The above command can also save the clone the contents of one domain to another if we are using ssh or sshfs to access a webserver. diff --git a/_episodes/08-command-substitution.md b/_episodes/08-command-substitution.md index 47788da..f2f96c7 100644 --- a/_episodes/08-command-substitution.md +++ b/_episodes/08-command-substitution.md @@ -7,7 +7,11 @@ questions: objectives: - Understand the need for flexibility regarding arguments - Generate the values of the arguments on the fly using command substitution -- Understand the difference between pipes/redirection, and the command substitution operator +- Understand the difference between pipes/redirection and the command substitution operator +keypoints: +- Command substitution can achieved by using dollar mark, `$(things to be replaced)`. +- Things to be replaced can be words and outputs of another command +- Command substitution can be used for inputs and output of another command, but the output side must be modified to avoid file replacements. --- ## Introduction @@ -162,15 +166,16 @@ simply because `cat cohort2010.txt | head -n 2` produces Everything between the `$(` and `)` is executed verbatim by the shell, so also the `-n 2` argument to the `head` command works as expected. -### **Important** - -Recall from the *Loops* and the *Shell Scripts* topics that Unix uses -whitespace to separate command, options (flags) and parameters / -arguments. For the same reason it is essential that the command (or -pipeline) inside the backticks produces *clean* output: single word -output works best within single commands and whitespace- or -newline-separated words work best for lists over which to iterate in -loops. +> ## Important +> +> Recall from the *Loops* and the *Shell Scripts* topics that Unix uses +> whitespace to separate command, options (flags) and parameters / +> arguments. For the same reason it is essential that the command (or +> pipeline) inside the backticks produces *clean* output: single word +> output works best within single commands and whitespace- or +> newline-separated words work best for lists over which to iterate in +> loops. +{: .callout} > ## Generating filenames based on a timestamp > diff --git a/_episodes/09-awk.md b/_episodes/09-awk.md index 73a464c..9767f5b 100644 --- a/_episodes/09-awk.md +++ b/_episodes/09-awk.md @@ -13,14 +13,15 @@ objectives: - "Use the `if-then` structure to change behaviour for the same matching regex" - "Introduce the array data structure" - "Use the for loop to cycle through an array" +keypoints: + --- -AWK is a tool for manipulating and filtering complex data. It stands for Aho, Weinberger, and Kernighan, the designers of this prgoram. This chapter requires understanding of previous shell lessons and any programming language. +AWK is a tool for manipulating and filtering complex data. It stands for Aho, Weinberger, and Kernighan, the designers of this program. This chapter requires understanding of previous shell lessons and any programming language. Let's start. -If we need to count the number of lines in a file, we can use the previously -showed command for word counting wc +If we need to count the number of lines in a file, we can use the previously shown command for word counting wc ~~~ {.bash} $ wc -l example.txt From ccc6ad62db651980677ba184eda16b6b387791a9 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Mon, 22 Apr 2024 11:09:19 +0900 Subject: [PATCH 15/18] add data for exercise --- _episodes/09-awk.md | 42 ++++---- data/README.md | 7 ++ data/example.txt | 11 ++ data/example2.txt | 241 ++++++++++++++++++++++++++++++++++++++++++++ data/methane.pdb | 9 ++ 5 files changed, 292 insertions(+), 18 deletions(-) create mode 100644 data/README.md create mode 100644 data/example.txt create mode 100644 data/example2.txt create mode 100644 data/methane.pdb diff --git a/_episodes/09-awk.md b/_episodes/09-awk.md index 9767f5b..57a00df 100644 --- a/_episodes/09-awk.md +++ b/_episodes/09-awk.md @@ -14,17 +14,20 @@ objectives: - "Introduce the array data structure" - "Use the for loop to cycle through an array" keypoints: - +- awk can be used to manipulate and filter data, e.g. adding text or printing specific columns +- NF is a variable that stores the number of fields in the current line +- Field separator can be specified with the `-F` option, default is space +- Matching patterns can be specified with `/^PATTERN/` instruction --- AWK is a tool for manipulating and filtering complex data. It stands for Aho, Weinberger, and Kernighan, the designers of this program. This chapter requires understanding of previous shell lessons and any programming language. -Let's start. +Let's start. The `example.txt` for exercise is available under `data` directory. You can also download it from [here](../data/example.txt). -If we need to count the number of lines in a file, we can use the previously shown command for word counting wc +If we need to count the number of lines in a file, we can use the previously shown command for word counting `wc`. ~~~ {.bash} -$ wc -l example.txt +wc -l example.txt ~~~ As you probably remember, -l is an option that asks for the number of lines only. @@ -32,8 +35,8 @@ As you probably remember, -l is an option that asks for the number of lines only However, wc counts the number of newlines in the file, if the last line does not contain a carriage return (i.e. there is no empty line at the end of the file), the result is going be the actual number of lines minus one. - -A workaround is to use Awk. Awk is command line program that takes as input a set + +A workaround is to use Awk. Awk is a command line program that takes as input a set of instructions and one or more files. The instructions are executed on each line of the input file(s). @@ -42,20 +45,21 @@ The instructions are enclosed in single quotes or they can be read from a file. Example: ~~~ {.bash} -$ awk '{print $0}' example.txt +awk '{print $0}' example.txt ~~~ This command has the same output as `cat`: it prints each line from the example.txt file. The structure of the instruction is the following: + - curly braces surround the set of instructions - print is the instruction that sends its arguments to the terminal - $0 is a variable, it means "the content of the current line" As you can see, the file contains a table. -Awk automatically splits the processed line by looking at spaces: in our case it has +Awk automatically splits the processed line by looking at spaces: in our case, it has knowledge of the different columns in the table. Each column value for the current line is stored into a variable: $1 for the first @@ -64,13 +68,13 @@ column, $2 for the second and so on. So, if we like to print only the second column from the table, we execute ~~~ {.bash} -$ awk '{print $2}' example.txt +awk '{print $2}' example.txt ~~~ -We can also print more than one value, or add text to the printed line: +We can also print more than one value, or add text (e.g. "chr") to the printed line: ~~~ {.bash} -$ awk '{print "chr",$2,$4}' example.txt +awk '{print "chr",$2,$4}' example.txt ~~~ The comma puts a space between the printed values. Strings of text should be enclosed in @@ -85,17 +89,18 @@ Awk helps us thanks to the variable NF. NF stores the number of fields (our colu row. Let's see for our table: ~~~ {.bash} -$ awk '{print NF}' example.txt +awk '{print NF}' example.txt ~~~ We can see that some lines contain 6 fields while others contain 7 of them. Since NF is the number of the last field, $NF contains its value. ~~~ {.bash} -$ awk '{print "This line has",NF,"columns. The last one contains",$NF}' example.txt +awk '{print "This line has",NF,"columns. The last one contains",$NF}' example.txt ~~~ -> ## Field separator +> ## Field separator +> > Out there we have different file formats: our data may be comma separated (csv), > tab separated (tsv), by a semicolon or by any other character. {: .callout} @@ -103,7 +108,7 @@ $ awk '{print "This line has",NF,"columns. The last one contains",$NF}' example. To specify the field separator, we should provide it at the command line like: ~~~ {.bash} -$ awk -F "," '{print $2}' example2.txt +awk -F "," '{print $2}' example2.txt ~~~ In this case, we are printing the second field in each line, using comma as separator. @@ -111,6 +116,7 @@ Please notice that the character space is now part of the field value, since it longer the separator. > ## Matching lines +> > Maybe we would like to perform different instructions on different lines. {: .callout} @@ -119,14 +125,14 @@ Awk allows you to specify a matching pattern, like the command grep does. Let's look at the file content ~~~ {.bash} -$ awk '{print $0}' example.pdb +awk '{print $0}' methane.pdb ~~~ It seems to be an abridged PDB file. If we would like to print only lines starting with the word "ATOM", we type: ~~~ {.bash} -awk '/^ATOM/ {print $0}' example.pdb +awk '/^ATOM/ {print $0}' methane.pdb ~~~ In this case, we specify the pattern before the instructions: only lines starting with the @@ -135,7 +141,7 @@ text "ATOM". As you remember, ^ means "at the beginning of the line". We can specify more than one pattern: ~~~ {.bash} -awk '/^ATOM/ {print $7,$8,$9} /^HEADER/ {print $NF}' example.pdb +awk '/^ATOM/ {print $7,$8,$9} /^HEADER/ {print $NF}' methane.pdb ~~~ In this case, we are printing the spatial coordinates of each atom. diff --git a/data/README.md b/data/README.md new file mode 100644 index 0000000..7044edb --- /dev/null +++ b/data/README.md @@ -0,0 +1,7 @@ +# Directory for data used in Shell Extras + +Data (filname: source): + +- example.txt: +- example2.txt: +- methane.pdb: SW Carpentry Shell Novice, shell-lesson-data/exercise/alkanes diff --git a/data/example.txt b/data/example.txt new file mode 100644 index 0000000..3841968 --- /dev/null +++ b/data/example.txt @@ -0,0 +1,11 @@ +CREDITS,EXPDATE,USER,GROUPS +99,01 jun 2018,sylvain,team:::admin +52,01 dec 2018,sonia,team +52,01 dec 2018,sonia,team +25,01 jan 2019,sonia,team +10,01 jan 2019,sylvain,team:::admin +8,12 jun 2018,öle,team:support + + + +17,05 apr 2019,abhishek,guest \ No newline at end of file diff --git a/data/example2.txt b/data/example2.txt new file mode 100644 index 0000000..7290757 --- /dev/null +++ b/data/example2.txt @@ -0,0 +1,241 @@ +file,emotion,speaker,gender +./Actor_21/03-01-07-01-01-01-21.wav,disgust,21,male +./Actor_21/03-01-06-01-02-02-21.wav,fear,21,male +./Actor_21/03-01-06-02-01-02-21.wav,fear,21,male +./Actor_21/03-01-04-02-01-02-21.wav,sad,21,male +./Actor_21/03-01-01-01-01-02-21.wav,neutral,21,male +./Actor_21/03-01-04-01-01-02-21.wav,sad,21,male +./Actor_21/03-01-06-02-01-01-21.wav,fear,21,male +./Actor_21/03-01-03-01-01-02-21.wav,happy,21,male +./Actor_21/03-01-01-01-02-02-21.wav,neutral,21,male +./Actor_21/03-01-03-01-01-01-21.wav,happy,21,male +./Actor_21/03-01-06-01-02-01-21.wav,fear,21,male +./Actor_21/03-01-05-01-01-02-21.wav,angry,21,male +./Actor_21/03-01-02-01-01-02-21.wav,calm,21,male +./Actor_21/03-01-05-01-01-01-21.wav,angry,21,male +./Actor_21/03-01-04-01-02-02-21.wav,sad,21,male +./Actor_21/03-01-07-01-01-02-21.wav,disgust,21,male +./Actor_21/03-01-03-02-01-01-21.wav,happy,21,male +./Actor_21/03-01-01-01-01-01-21.wav,neutral,21,male +./Actor_21/03-01-07-01-02-01-21.wav,disgust,21,male +./Actor_21/03-01-02-01-02-02-21.wav,calm,21,male +./Actor_21/03-01-07-02-02-01-21.wav,disgust,21,male +./Actor_21/03-01-05-02-01-02-21.wav,angry,21,male +./Actor_21/03-01-02-02-01-02-21.wav,calm,21,male +./Actor_21/03-01-06-02-02-02-21.wav,fear,21,male +./Actor_21/03-01-05-01-02-01-21.wav,angry,21,male +./Actor_21/03-01-04-02-02-02-21.wav,sad,21,male +./Actor_21/03-01-01-01-02-01-21.wav,neutral,21,male +./Actor_21/03-01-03-01-02-01-21.wav,happy,21,male +./Actor_21/03-01-07-02-01-02-21.wav,disgust,21,male +./Actor_21/03-01-08-01-02-02-21.wav,surprise,21,male +./Actor_21/03-01-05-02-01-01-21.wav,angry,21,male +./Actor_21/03-01-08-02-02-01-21.wav,surprise,21,male +./Actor_21/03-01-06-01-01-01-21.wav,fear,21,male +./Actor_21/03-01-05-02-02-02-21.wav,angry,21,male +./Actor_21/03-01-04-01-02-01-21.wav,sad,21,male +./Actor_21/03-01-04-02-01-01-21.wav,sad,21,male +./Actor_21/03-01-06-02-02-01-21.wav,fear,21,male +./Actor_21/03-01-02-02-02-01-21.wav,calm,21,male +./Actor_21/03-01-08-02-01-01-21.wav,surprise,21,male +./Actor_21/03-01-08-01-01-02-21.wav,surprise,21,male +./Actor_21/03-01-05-02-02-01-21.wav,angry,21,male +./Actor_21/03-01-08-01-02-01-21.wav,surprise,21,male +./Actor_21/03-01-08-02-01-02-21.wav,surprise,21,male +./Actor_21/03-01-03-01-02-02-21.wav,happy,21,male +./Actor_21/03-01-07-01-02-02-21.wav,disgust,21,male +./Actor_21/03-01-08-01-01-01-21.wav,surprise,21,male +./Actor_21/03-01-02-02-02-02-21.wav,calm,21,male +./Actor_21/03-01-02-02-01-01-21.wav,calm,21,male +./Actor_21/03-01-02-01-02-01-21.wav,calm,21,male +./Actor_21/03-01-08-02-02-02-21.wav,surprise,21,male +./Actor_21/03-01-04-02-02-01-21.wav,sad,21,male +./Actor_21/03-01-06-01-01-02-21.wav,fear,21,male +./Actor_21/03-01-07-02-02-02-21.wav,disgust,21,male +./Actor_21/03-01-03-02-02-02-21.wav,happy,21,male +./Actor_21/03-01-04-01-01-01-21.wav,sad,21,male +./Actor_21/03-01-02-01-01-01-21.wav,calm,21,male +./Actor_21/03-01-07-02-01-01-21.wav,disgust,21,male +./Actor_21/03-01-03-02-02-01-21.wav,happy,21,male +./Actor_21/03-01-03-02-01-02-21.wav,happy,21,male +./Actor_21/03-01-05-01-02-02-21.wav,angry,21,male +./Actor_23/03-01-03-02-01-02-23.wav,happy,23,male +./Actor_23/03-01-02-01-01-02-23.wav,calm,23,male +./Actor_23/03-01-04-01-01-02-23.wav,sad,23,male +./Actor_23/03-01-07-02-02-02-23.wav,disgust,23,male +./Actor_23/03-01-05-02-02-01-23.wav,angry,23,male +./Actor_23/03-01-06-01-01-02-23.wav,fear,23,male +./Actor_23/03-01-08-01-01-02-23.wav,surprise,23,male +./Actor_23/03-01-06-02-01-01-23.wav,fear,23,male +./Actor_23/03-01-05-02-02-02-23.wav,angry,23,male +./Actor_23/03-01-05-01-02-02-23.wav,angry,23,male +./Actor_23/03-01-02-01-01-01-23.wav,calm,23,male +./Actor_23/03-01-07-01-02-01-23.wav,disgust,23,male +./Actor_23/03-01-01-01-02-01-23.wav,neutral,23,male +./Actor_23/03-01-03-02-02-02-23.wav,happy,23,male +./Actor_23/03-01-07-01-01-02-23.wav,disgust,23,male +./Actor_23/03-01-01-01-01-02-23.wav,neutral,23,male +./Actor_23/03-01-01-01-01-01-23.wav,neutral,23,male +./Actor_23/03-01-02-02-02-01-23.wav,calm,23,male +./Actor_23/03-01-05-02-01-02-23.wav,angry,23,male +./Actor_23/03-01-07-02-02-01-23.wav,disgust,23,male +./Actor_23/03-01-08-01-01-01-23.wav,surprise,23,male +./Actor_23/03-01-03-02-01-01-23.wav,happy,23,male +./Actor_23/03-01-08-02-01-02-23.wav,surprise,23,male +./Actor_23/03-01-03-01-02-02-23.wav,happy,23,male +./Actor_23/03-01-08-02-02-02-23.wav,surprise,23,male +./Actor_23/03-01-06-01-01-01-23.wav,fear,23,male +./Actor_23/03-01-07-01-01-01-23.wav,disgust,23,male +./Actor_23/03-01-08-02-01-01-23.wav,surprise,23,male +./Actor_23/03-01-02-02-01-01-23.wav,calm,23,male +./Actor_23/03-01-03-01-02-01-23.wav,happy,23,male +./Actor_23/03-01-05-01-02-01-23.wav,angry,23,male +./Actor_23/03-01-02-01-02-02-23.wav,calm,23,male +./Actor_23/03-01-04-02-02-02-23.wav,sad,23,male +./Actor_23/03-01-06-02-02-01-23.wav,fear,23,male +./Actor_23/03-01-06-01-02-02-23.wav,fear,23,male +./Actor_23/03-01-05-01-01-01-23.wav,angry,23,male +./Actor_23/03-01-04-01-02-01-23.wav,sad,23,male +./Actor_23/03-01-01-01-02-02-23.wav,neutral,23,male +./Actor_23/03-01-07-02-01-01-23.wav,disgust,23,male +./Actor_23/03-01-04-02-01-01-23.wav,sad,23,male +./Actor_23/03-01-08-01-02-01-23.wav,surprise,23,male +./Actor_23/03-01-03-01-01-02-23.wav,happy,23,male +./Actor_23/03-01-07-01-02-02-23.wav,disgust,23,male +./Actor_23/03-01-02-01-02-01-23.wav,calm,23,male +./Actor_23/03-01-06-01-02-01-23.wav,fear,23,male +./Actor_23/03-01-05-01-01-02-23.wav,angry,23,male +./Actor_23/03-01-06-02-01-02-23.wav,fear,23,male +./Actor_23/03-01-02-02-01-02-23.wav,calm,23,male +./Actor_23/03-01-04-02-02-01-23.wav,sad,23,male +./Actor_23/03-01-04-02-01-02-23.wav,sad,23,male +./Actor_23/03-01-05-02-01-01-23.wav,angry,23,male +./Actor_23/03-01-07-02-01-02-23.wav,disgust,23,male +./Actor_23/03-01-02-02-02-02-23.wav,calm,23,male +./Actor_23/03-01-04-01-01-01-23.wav,sad,23,male +./Actor_23/03-01-06-02-02-02-23.wav,fear,23,male +./Actor_23/03-01-03-01-01-01-23.wav,happy,23,male +./Actor_23/03-01-04-01-02-02-23.wav,sad,23,male +./Actor_23/03-01-03-02-02-01-23.wav,happy,23,male +./Actor_23/03-01-08-02-02-01-23.wav,surprise,23,male +./Actor_23/03-01-08-01-02-02-23.wav,surprise,23,male +./Actor_22/03-01-02-01-01-01-22.wav,calm,22,female +./Actor_22/03-01-05-01-02-01-22.wav,angry,22,female +./Actor_22/03-01-03-02-01-02-22.wav,happy,22,female +./Actor_22/03-01-04-01-02-01-22.wav,sad,22,female +./Actor_22/03-01-05-02-02-02-22.wav,angry,22,female +./Actor_22/03-01-08-02-02-02-22.wav,surprise,22,female +./Actor_22/03-01-04-02-02-02-22.wav,sad,22,female +./Actor_22/03-01-02-01-02-02-22.wav,calm,22,female +./Actor_22/03-01-03-02-01-01-22.wav,happy,22,female +./Actor_22/03-01-06-01-01-01-22.wav,fear,22,female +./Actor_22/03-01-07-01-01-02-22.wav,disgust,22,female +./Actor_22/03-01-04-02-01-01-22.wav,sad,22,female +./Actor_22/03-01-07-01-02-02-22.wav,disgust,22,female +./Actor_22/03-01-04-02-02-01-22.wav,sad,22,female +./Actor_22/03-01-06-01-01-02-22.wav,fear,22,female +./Actor_22/03-01-03-02-02-02-22.wav,happy,22,female +./Actor_22/03-01-07-02-01-01-22.wav,disgust,22,female +./Actor_22/03-01-08-02-01-02-22.wav,surprise,22,female +./Actor_22/03-01-01-01-02-01-22.wav,neutral,22,female +./Actor_22/03-01-03-02-02-01-22.wav,happy,22,female +./Actor_22/03-01-03-01-01-01-22.wav,happy,22,female +./Actor_22/03-01-05-02-01-01-22.wav,angry,22,female +./Actor_22/03-01-08-01-02-01-22.wav,surprise,22,female +./Actor_22/03-01-03-01-01-02-22.wav,happy,22,female +./Actor_22/03-01-02-01-02-01-22.wav,calm,22,female +./Actor_22/03-01-05-02-02-01-22.wav,angry,22,female +./Actor_22/03-01-06-02-02-02-22.wav,fear,22,female +./Actor_22/03-01-03-01-02-02-22.wav,happy,22,female +./Actor_22/03-01-05-02-01-02-22.wav,angry,22,female +./Actor_22/03-01-01-01-01-02-22.wav,neutral,22,female +./Actor_22/03-01-07-01-01-01-22.wav,disgust,22,female +./Actor_22/03-01-04-01-01-01-22.wav,sad,22,female +./Actor_22/03-01-02-02-01-01-22.wav,calm,22,female +./Actor_22/03-01-06-01-02-01-22.wav,fear,22,female +./Actor_22/03-01-02-02-02-02-22.wav,calm,22,female +./Actor_22/03-01-08-02-01-01-22.wav,surprise,22,female +./Actor_22/03-01-08-01-02-02-22.wav,surprise,22,female +./Actor_22/03-01-02-02-01-02-22.wav,calm,22,female +./Actor_22/03-01-02-01-01-02-22.wav,calm,22,female +./Actor_22/03-01-05-01-01-02-22.wav,angry,22,female +./Actor_22/03-01-04-01-01-02-22.wav,sad,22,female +./Actor_22/03-01-08-01-01-01-22.wav,surprise,22,female +./Actor_22/03-01-06-02-01-02-22.wav,fear,22,female +./Actor_22/03-01-07-02-02-01-22.wav,disgust,22,female +./Actor_22/03-01-06-02-02-01-22.wav,fear,22,female +./Actor_22/03-01-06-02-01-01-22.wav,fear,22,female +./Actor_22/03-01-07-02-01-02-22.wav,disgust,22,female +./Actor_22/03-01-08-01-01-02-22.wav,surprise,22,female +./Actor_22/03-01-01-01-02-02-22.wav,neutral,22,female +./Actor_22/03-01-06-01-02-02-22.wav,fear,22,female +./Actor_22/03-01-02-02-02-01-22.wav,calm,22,female +./Actor_22/03-01-05-01-01-01-22.wav,angry,22,female +./Actor_22/03-01-03-01-02-01-22.wav,happy,22,female +./Actor_22/03-01-01-01-01-01-22.wav,neutral,22,female +./Actor_22/03-01-04-01-02-02-22.wav,sad,22,female +./Actor_22/03-01-05-01-02-02-22.wav,angry,22,female +./Actor_22/03-01-04-02-01-02-22.wav,sad,22,female +./Actor_22/03-01-08-02-02-01-22.wav,surprise,22,female +./Actor_22/03-01-07-02-02-02-22.wav,disgust,22,female +./Actor_22/03-01-07-01-02-01-22.wav,disgust,22,female +./Actor_24/03-01-02-02-01-01-24.wav,calm,24,female +./Actor_24/03-01-05-02-01-01-24.wav,angry,24,female +./Actor_24/03-01-01-01-01-01-24.wav,neutral,24,female +./Actor_24/03-01-07-01-01-01-24.wav,disgust,24,female +./Actor_24/03-01-05-02-02-01-24.wav,angry,24,female +./Actor_24/03-01-03-01-01-01-24.wav,happy,24,female +./Actor_24/03-01-05-02-01-02-24.wav,angry,24,female +./Actor_24/03-01-02-01-01-01-24.wav,calm,24,female +./Actor_24/03-01-02-01-02-02-24.wav,calm,24,female +./Actor_24/03-01-05-02-02-02-24.wav,angry,24,female +./Actor_24/03-01-06-01-02-02-24.wav,fear,24,female +./Actor_24/03-01-03-02-02-02-24.wav,happy,24,female +./Actor_24/03-01-07-02-02-01-24.wav,disgust,24,female +./Actor_24/03-01-04-02-01-01-24.wav,sad,24,female +./Actor_24/03-01-01-01-02-02-24.wav,neutral,24,female +./Actor_24/03-01-02-01-02-01-24.wav,calm,24,female +./Actor_24/03-01-08-01-02-01-24.wav,surprise,24,female +./Actor_24/03-01-06-02-02-02-24.wav,fear,24,female +./Actor_24/03-01-07-02-02-02-24.wav,disgust,24,female +./Actor_24/03-01-04-01-01-01-24.wav,sad,24,female +./Actor_24/03-01-06-01-01-02-24.wav,fear,24,female +./Actor_24/03-01-03-02-01-02-24.wav,happy,24,female +./Actor_24/03-01-04-02-01-02-24.wav,sad,24,female +./Actor_24/03-01-05-01-02-01-24.wav,angry,24,female +./Actor_24/03-01-05-01-02-02-24.wav,angry,24,female +./Actor_24/03-01-06-02-02-01-24.wav,fear,24,female +./Actor_24/03-01-01-01-02-01-24.wav,neutral,24,female +./Actor_24/03-01-04-01-02-02-24.wav,sad,24,female +./Actor_24/03-01-02-02-01-02-24.wav,calm,24,female +./Actor_24/03-01-01-01-01-02-24.wav,neutral,24,female +./Actor_24/03-01-03-01-02-02-24.wav,happy,24,female +./Actor_24/03-01-08-01-01-01-24.wav,surprise,24,female +./Actor_24/03-01-06-01-02-01-24.wav,fear,24,female +./Actor_24/03-01-03-02-02-01-24.wav,happy,24,female +./Actor_24/03-01-06-01-01-01-24.wav,fear,24,female +./Actor_24/03-01-06-02-01-02-24.wav,fear,24,female +./Actor_24/03-01-02-01-01-02-24.wav,calm,24,female +./Actor_24/03-01-03-01-02-01-24.wav,happy,24,female +./Actor_24/03-01-07-02-01-02-24.wav,disgust,24,female +./Actor_24/03-01-06-02-01-01-24.wav,fear,24,female +./Actor_24/03-01-05-01-01-01-24.wav,angry,24,female +./Actor_24/03-01-08-02-02-02-24.wav,surprise,24,female +./Actor_24/03-01-02-02-02-01-24.wav,calm,24,female +./Actor_24/03-01-08-01-02-02-24.wav,surprise,24,female +./Actor_24/03-01-07-01-02-01-24.wav,disgust,24,female +./Actor_24/03-01-04-01-02-01-24.wav,sad,24,female +./Actor_24/03-01-07-02-01-01-24.wav,disgust,24,female +./Actor_24/03-01-08-02-01-01-24.wav,surprise,24,female +./Actor_24/03-01-04-02-02-02-24.wav,sad,24,female +./Actor_24/03-01-04-02-02-01-24.wav,sad,24,female +./Actor_24/03-01-07-01-01-02-24.wav,disgust,24,female +./Actor_24/03-01-02-02-02-02-24.wav,calm,24,female +./Actor_24/03-01-05-01-01-02-24.wav,angry,24,female +./Actor_24/03-01-04-01-01-02-24.wav,sad,24,female +./Actor_24/03-01-07-01-02-02-24.wav,disgust,24,female +./Actor_24/03-01-03-02-01-01-24.wav,happy,24,female +./Actor_24/03-01-08-02-02-01-24.wav,surprise,24,female +./Actor_24/03-01-08-01-01-02-24.wav,surprise,24,female +./Actor_24/03-01-03-01-01-02-24.wav,happy,24,female +./Actor_24/03-01-08-02-01-02-24.wav,surprise,24,female diff --git a/data/methane.pdb b/data/methane.pdb new file mode 100644 index 0000000..7908351 --- /dev/null +++ b/data/methane.pdb @@ -0,0 +1,9 @@ +COMPND METHANE +AUTHOR DAVE WOODCOCK 95 12 18 +ATOM 1 C 1 0.257 -0.363 0.000 1.00 0.00 +ATOM 2 H 1 0.257 0.727 0.000 1.00 0.00 +ATOM 3 H 1 0.771 -0.727 0.890 1.00 0.00 +ATOM 4 H 1 0.771 -0.727 -0.890 1.00 0.00 +ATOM 5 H 1 -0.771 -0.727 0.000 1.00 0.00 +TER 6 1 +END From 935855edf02c82b1196909c4ad16b23f2d7b9991 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Mon, 22 Apr 2024 11:14:25 +0900 Subject: [PATCH 16/18] update permissions, change all to others --- _episodes/04-permissions.md | 61 +++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/_episodes/04-permissions.md b/_episodes/04-permissions.md index 6e50e80..5e0ad06 100644 --- a/_episodes/04-permissions.md +++ b/_episodes/04-permissions.md @@ -86,9 +86,9 @@ For example, if a file had the following set of permissions: it would mean that: -* the file's owner can read and write it, but not run it; -* other people in the file's group can read it, but not modify it or run it; and -* everybody else can do nothing with it at all. +* the file's owner can read and write it, but not run it; +* other people in the file's group can read it, but not modify it or run it; and +* everybody else can do nothing with it at all. Let's look at this model in action. If we `cd` into the `labs` directory and run `ls -F`, @@ -98,13 +98,16 @@ i.e., that it's (probably) something the computer can run. ~~~ -$ cd labs -$ ls -F +cd labs +ls -F ~~~ + {: .bash} + ~~~ safety.txt setup* waiver.txt ~~~ + {: .output} > ## Necessary But Not Sufficient @@ -124,14 +127,17 @@ safety.txt setup* waiver.txt Now let's run the command `ls -l`: ~~~ -$ ls -l +ls -l ~~~ + {: .bash} + ~~~ -rw-rw-r-- 1 vlad bio 1158 2010-07-11 08:22 safety.txt -rwxr-xr-x 1 vlad bio 31988 2010-07-23 20:04 setup -rw-rw-r-- 1 vlad bio 2312 2010-07-11 08:23 waiver.txt ~~~ + {: .output} The `-l` flag tells `ls` to give us a long-form listing. @@ -173,13 +179,15 @@ Here's a long-form listing showing the permissions on the final grades in the course Vlad is teaching: ~~~ -$ ls -l final.grd +ls -l final.grd ~~~ + {: .bash} ~~~ -rwxrwxrwx 1 vlad bio 4215 2010-08-29 22:30 final.grd ~~~ + {: .output} Whoops: everyone in the world can read it—and what's worse, @@ -190,8 +198,9 @@ which would almost certainly not work.) The command to change the owner's permissions to `rw-` is: ~~~ -$ chmod u=rw final.grd +chmod u=rw final.grd ~~~ + {: .bash} The 'u' signals that we're changing the privileges @@ -201,60 +210,68 @@ A quick `ls -l` shows us that it worked, because the owner's permissions are now set to read and write: ~~~ -$ ls -l final.grd +ls -l final.grd ~~~ + {: .bash} ~~~ -rw-rwxrwx 1 vlad bio 4215 2010-08-30 08:19 final.grd ~~~ + {: .output} Let's run `chmod` again to give the group read-only permission: ~~~ -$ chmod g=r final.grd -$ ls -l final.grd +chmod g=r final.grd +ls -l final.grd ~~~ + {: .bash} ~~~ -rw-r--rw- 1 vlad bio 4215 2010-08-30 08:19 final.grd ~~~ + {: .output} And finally, -let's give "all" (everyone on the system who isn't the file's owner or in its group) no permissions at all: +let's give "others" (everyone on the system who isn't the file's owner or in its group) no permissions at all: ~~~ -$ chmod a= final.grd -$ ls -l final.grd +chmod o= final.grd +ls -l final.grd ~~~ + {: .bash} ~~~ -rw-r----- 1 vlad bio 4215 2010-08-30 08:20 final.grd ~~~ + {: .output} Here, -the 'a' signals that we're changing permissions for "all", +the 'o' signals that we're changing permissions for "others", and since there's nothing on the right of the "=", -"all"'s new permissions are empty. +"others"'s new permissions are empty. We can search by permissions, too. Here, for example, we can use `-type f -perm -u=x` to find files that the user can execute: ~~~ -$ find . -type f -perm -u=x +find . -type f -perm -u=x ~~~ + {: .bash} ~~~ ./tools/format ./tools/stats ~~~ + {: .output} Before we go any further, @@ -262,8 +279,9 @@ let's run `ls -a -l` to get a long-form listing that includes directory entries that are normally hidden: ~~~ -$ ls -a -l +ls -a -l ~~~ + {: .bash} ~~~ @@ -273,6 +291,7 @@ drwxr-xr-x 1 vlad bio 8192 2010-08-27 23:11 .. -rwxr-xr-x 1 vlad bio 31988 2010-07-23 20:04 setup -rw-rw-r-- 1 vlad bio 2312 2010-07-11 08:23 waiver.txt ~~~ + {: .output} The permissions for `.` and `..` (this directory and its parent) start with a 'd'. @@ -322,15 +341,17 @@ Some modern variants of Unix support ACLs as well as the older read-write-execut but hardly anyone uses them. > ## Challenge +> > If `ls -l myfile.php` returns the following details: > > ~~~ > -rwxr-xr-- 1 caro zoo 2312 2014-10-25 18:30 myfile.php > ~~~ +> > {: .output} -> +> > Which of the following statements is true? -> +> > 1. caro (the owner) can read, write, and execute myfile.php > 2. caro (the owner) cannot write to myfile.php > 3. members of caro (a group) can read, write, and execute myfile.php From 0a9b60ea0caab77df10f0c884f6668521bc78ecd Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Mon, 22 Apr 2024 11:44:29 +0900 Subject: [PATCH 17/18] add example file for shebang --- _episodes/04-permissions.md | 13 +++++++++++++ code/file_info.sh | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100755 code/file_info.sh diff --git a/_episodes/04-permissions.md b/_episodes/04-permissions.md index 5e0ad06..4cda952 100644 --- a/_episodes/04-permissions.md +++ b/_episodes/04-permissions.md @@ -322,6 +322,19 @@ She's allowed to go through `pluto`, but not to look at what's there. This trick gives people a way to make some of their directories visible to the world as a whole without opening up everything else. +## Shebang + +Shebang is the #! syntax used in scripts to indicate an interpreter for execution under UNIX/Linux operating systems. For shell, we can use two different approaches, + +~~~{.bash} +#!/bin/bash +# OR +#!/usr/bin/env bash +~~~ + +at the top of script. The second approach is more portable and recommended. For +instance check the `file_info.sh` script in the `code` directory. First, + ## What about Windows? Those are the basics of permissions on Unix. diff --git a/code/file_info.sh b/code/file_info.sh new file mode 100755 index 0000000..226fd95 --- /dev/null +++ b/code/file_info.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# This script is used to show the number line of a file +# Usage: ./file_info.sh +# Output: has lines and size of + +# Check if the number of arguments is less than 1 +if [ $# -lt 1 ]; then + echo "Usage: ./show_line_number.sh " + exit 1 +fi + + +# Check if the file exists +if [ ! -f $1 ]; then + echo "File not found" + exit 1 +fi + +# Count the number of lines in the file +line_number=$(wc -l < $1) + +# Count the size of the file +size=$(du -h $1 | cut -f1) + +# Display the filename, number of lines and size of the file +echo "$1 has $line_number lines and size of $size" From e24112585e429efa738cf9ebb5a9826e4916f269 Mon Sep 17 00:00:00 2001 From: Bagus Tris Atmaja Date: Mon, 22 Apr 2024 11:57:38 +0900 Subject: [PATCH 18/18] update shebang --- _episodes/04-permissions.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/_episodes/04-permissions.md b/_episodes/04-permissions.md index 4cda952..c685c35 100644 --- a/_episodes/04-permissions.md +++ b/_episodes/04-permissions.md @@ -328,12 +328,33 @@ Shebang is the #! syntax used in scripts to indicate an interpreter for executio ~~~{.bash} #!/bin/bash -# OR +~~~ + +or, + +~~~{.bash} #!/usr/bin/env bash ~~~ -at the top of script. The second approach is more portable and recommended. For -instance check the `file_info.sh` script in the `code` directory. First, +at the top of the script. The second approach is more portable and recommended. +For instance, check the `file_info.sh` script in the `code` directory. +First, after creating or downloading the script, we need to make it executable using `chmod` command. + +~~~{.bash} +chmod u+x file_info.sh +~~~ + +The `u+x` option is used to permit the "**u**ser to e**x**ecute" the script. +Then we can run the script using the following command: + +~~~{.bash} +./file_info.sh example.txt +~~~ + +Shebang is necessary if we want to run the code without explicitly telling Unix what the interpreter is. +We still run the code without shebang, i.e., by telling the interpreter to run the code, +e.g., `bash file_info.sh example.txt`. If we run the code directly but no shebang +is given, or the permission is not given, the code will not run ("Permission denied" error). ## What about Windows?