FAQ
1. Arguments in if Statement
if Statement1.1. File
-e
The given path exists
-d
The given path is a directory
-f
The given path is a file
-r
The given path is readable
-w
The given path is writable
-x
The given path is executable
1.2. String
==
string equal
!=
string not equal
-z
string is empty
-n
string is not empty
1.3. Number
-eq
equal to
-ne
not equal to
-gt
greater than
-ge
greater than or equal to
-lt
less than
-le
less than or equal to
2. shift variables
shift variablesNote:
$0won't be changed byshiftcommand.
The shift command literally shifts the command-line parameters in their relative positions.
When you use the shift command, it moves each parameter variable one position to the left by default. Thus, the value for variable $3 is moved to $2 , the value for variable $2 is moved to $1 , and the value for variable $1 is discarded (note that the value for variable $0 , the program name, remains unchanged).
This is another great way to iterate through command-line parameters. You can just operate on the first parameter, shift the parameters over, and then operate on the first parameter again.
2.1. shift one parameter
Here's a short demonstration of how this works:
shift-params.sh:
NOTE: Be careful when working with the shift command. When a parameter is shifted out, its value is lost and can't be recovered.
2.2. shift multiple parameters
Alternatively, you can perform a multiple location shift by providing a parameter to the shift command. Just provide the number of places you want to shift:
big-shift-params.sh:
By using values in the shift command, you can easily skip over parameters you don't need in certain situations.
3. Special variables in Bash
3.1. $?
$?Exit status of a command
0: Command run success1: Command failed during run2: Incorrect command usage127: Command not found
3.2. $0
$0You can use $0 to obtain the corresponding program name which is executed in shell scripts:
If you use relative path, for example,
./test.sh, then$0equals to./test.sh;If you use absolute path, for example,
/User/username/test.sh, then$0equals to/User/username/test.sh.
So, if you just want to get the program file name without path, you can use basename command in shell script:
3.3. $# and ${!#}
$# and ${!#}$# is used for getting the number of parameters.
If you need to get the last parameter, you cannot use ${$#}, because you shouldn't use $ sign inside the {} pair. You have two choices:
Use a temp parameter:
Use
${!#}(change$to!inside the{}pair).
3.4. $* and $@
$* and $@Both $* and $@ variables provide quick access to all parameters. The difference appears when the special parameters are quoted:
$*
$1 $2 $3 … ${N}
$@
$1 $2 $3 … ${N}
"$*"
"$1c$2c$3c…c${N}"
"$@"
"$1" "$2" "$3" … "${N}"
where c in the third row is the first character of $IFS, the Input Field Separator, a shell variable.
4. What's indirectly reference in Bash?
Indirect referencing in Bash means using the value of a variable to dynamically determine the name of another variable. This allows you to access variables indirectly, based on the value of another variable.
For example, consider the following script:
In this script, var_name contains the name of another variable (my_variable). ${!var_name} is used to access the value of the variable whose name is stored in var_name. So, it dynamically resolves to ${my_variable}, resulting in the output:
Here, the indirect reference ${!var_name} allows you to access the variable whose name is stored in var_name.
Similarly, ${!#} in Bash allows you to indirectly reference the last argument provided to a script or function. It evaluates to the value of the variable whose name is the result of the expansion of # (which represents the number of arguments passed). This is a way to dynamically access the last argument without explicitly using its position.
5. How to display $PATH as one directory per line?
$PATH as one directory per line?From ask ubuntu.
Question:
By default, the output of PATH is separated by colon:
The above display style is hard for human to read, it will be better if directories in PATH is displayed in single lines:
Solution:
You can do this with any one of the following commands, which substitutes all occurrences of : with new lines .
sed:
awk:
Note: In the example below,
1is used to print each modified line. Essentially, it's a pattern that always evaluates totrue, so it prints every line after the substitution. This is a common AWK idiom.
tr:
python:
Add function to ~/.zshrc:
Then you can use mypath to display directories in PATH in single lines.
6. What's the difference between << and <<<
<< and <<<From ask ubuntu
6.1. Here Document: output multi lines
<< is known as here-document structure. You let the program know what will be the ending text, and whenever that delimiter is seen, the program will read all the stuff you've given to the program as input and perform a task upon it.
e.g. 1
wc: The wc utility displays the number of lines, words, and bytes contained in each input file, or standard input (if no file is specified) to the standard output.
Output:
e.g. 2
Output:
6.2. Here String Usage
<<< is known as here-string. Instead of typing in text, you give a pre-made string of text to a program. For example, with such program as bc we can do bc <<< 5*4 to just get output for that specific case, no need to run bc interactively. Think of it as the equivalent of echo '5*4' | bc.
7. What does 2>&1 or &> mean?
2>&1 or &> mean?Note:
&>is a shorthand way of writing2>&1
In Unix-based systems, file descriptors are numbers associated with open files. By convention, file descriptor 0 is stdin, 1 is stdout, and 2 is stderr.
O:STDIN1:STDOUT2:STDERR
2>&1 is a shell redirection operator to redirect the standard error (stderr) to the same location as standard output (stdout). Let's break it down:
2: This refers to file descriptor2, which isstderr.>: This is the output redirection operator. It's used to redirect output from one location to another.&: This indicates that what follows is a file descriptor, rather than a filename.1: This refers to file descriptor1, which isstdout.
So, 2>&1 means "redirect file descriptor 2 (stderr) to the same location as file descriptor 1 (stdout)". This is often used to capture both standard output and standard error in the same stream.
For example, consider the command:
8. Print Information of Java
Why
✅
java --version 2>&1 | grep "VM"works,
but
❌
java --version &> | grep "VM"doesn't work?
In Bash, the &> operator is a shorthand way of writing 2>&1, it's used for redirecting both stdout and stderr to a file or a command.
However, there maybe some restrictions to use the shorthand version &> in some scenarios, for example, in the second command, there is a misplaced pipe (|) symbol after &>, which is causing a syntax error.
The corrected version of the second command should be:
This command redirects both stdout and stderr to a process substitution that runs the grep "VM" command. This achieves the same result as the first command.
9. When do we use /dev/null in Bash?
/dev/null in Bash?/dev/null is a special device file that serves as a "bit bucket" or a black hole for data. It is often used in Bash for various purposes, including:
Discarding Output:
This
commandredirects the standard output ofcommandto/dev/null, effectively discarding any output that would have been displayed on the terminal.Suppressing Output:
This
commandredirects both standard output and standard error to/dev/null, effectively silencing thecommand.Checking if a Command Succeeds:
This checks if
commandsucceeds, but discards any output. It's useful when you're only interested in the success or failure of a command, not its output.
10. Process Substitution
10.1. Introduction
Process substitution is a form of inter-process communication(IPC) that allows the input or output of a command to appear as a file. The command is substituted in-line, where a file name would normally occur, by the command shell. This allows programs that normally only accept files to directly read from or write to another program.
Process substitution uses anonymous pipes behind the scenes to facilitate communication between processes.
When you use process substitution, such as in the form >(command) or <(command), a special file is created in the /dev/fd directory. This file acts as a placeholder or handle for the input or output stream of the process. Behind the scenes, this placeholder is implemented using an anonymous pipe.
For example, in the command java --version &> >(grep "VM"), the >(grep "VM") part is a process substitution. It creates a special file that represents the output of the command grep "VM". This special file is then used as an argument to the &> operator, effectively redirecting both stdout and stderr to the anonymous pipe created by the process substitution.
So, in summary, process substitution relies on anonymous pipes to establish a communication channel between processes, allowing them to interact with each other.
e.g. 1.1
Reference: shellcheck/SC2031
There are many ways of accidentally creating subshells, but a common one is piping to a loop:
Problematic code:
Correct code:
Rationale:
Variables set in subshells are not available outside the subshell.
e.g. 1.2
Another approach to solve subshell problem is by using named pipes to establish communication between the processes. Here's how you can do it:
This example is generated by ChatGPT 3.5
e.g. 2
The Unix diff command normally accepts the names of two files to compare, or one file name and standard input. Process substitution allows one to compare the output of two programs directly:
The <(command) expression tells the command interpreter to run command and make its output appear as a file. The command can be any arbitrarily complex shell command.
Without process substitution, the alternatives are save the output of the command(s) to a temporary file, then read the temporary file(s):
10.2. Difference between Process Substitution and Pipe
From Stack Exchange
Let's use the date command for testing.
This is a pointless example but it shows that cat accepted the output of date on STDIN and spit it back out. The same results can be achieved by process substitution:
However what just happened behind the scenes was different. Instead of being given a STDIN stream, cat was actually passed the name of a file that it needed to go open and read. You can see this step by using echo instead of cat.
When cat received the file name, it read the file's content for us. On the other hand, echo just showed us the file's name that it was passed. This difference becomes more obvious if you add more substitutions:
It is possible to combine process substitution (which generates a file) and input redirection (which connects a file to STDIN):
It looks pretty much the same but this time cat was passed STDIN stream instead of a file name. You can see this by trying it with echo:
Since echo doesn't read STDIN and no argument was passed, we get nothing.
Pipes and input redirects shove content onto the STDIN stream. Process substitution runs the commands, saves their output to a special temporary file and then passes that file name in place of the command. Whatever command you are using treats it as a file name. Note that the file created is not a regular file but a named pipe that gets removed automatically once it is no longer needed.
11. Process Status
11.1. ps aux
ps auxThe ps aux command is a common and powerful way to list information about processes in Unix-like operating systems.
ps: This is the command itself and it stands for "process status". It is used to view information about running processes.
a: This option tells ps to list information about all processes associated with terminals. It includes processes from all users.u: This option provides a more detailed output, including the user and other additional information about each process.x: This option adds processes not attached to a terminal. It includes background processes and daemons.
When you combine these options with ps aux, you're asking the system to list detailed information about all processes, including those of other users, both attached and not attached to a terminal.
Last updated