📝 我的笔记

还没有笔记

选中页面文字后点击「高亮」按钮添加

文件系统和 Bash 基础

📜 原文
📖 逐步解释
∑ 公式拆解
💡 数值示例
⚠️ 易错点
📝 总结
🎯 存在目的
🧠 直觉心智模型
💭 直观想象

1文件系统和 Bash 基础

COMS W3157

Borowski 博士

1 理解 ls -l

```

$ ls -l

total 36 <- total number of blocks used

drwxrwxr-x 2 user user 4096 Jan 28 23:36 Desktop

drwxr-xr-x 2 user user 4096 Jan 23 14:47 Documents

...

drwxrwxr-x

```

第一个字符是文件类型d -> 目录l -> 链接c -> 字符设备b -> 块设备- -> 常规文件。第一个 rwx 表示用户具有读、写和执行权限。第二个 rwx 表示组具有读、写和执行权限。第三组是 r-x,其他用户没有写权限。

2 理解 ls -l

```

$ ls -l

total 36

drwxrwxr-x 2 user user 4096 Jan 28 23:36 Desktop

drwxr-xr-x 2 user user 4096 Jan 23 14:47 Documents

...

```

硬链接计数是红色的。

拥有该文件的用户是蓝色的。

是绿色的。

文件大小(以字节为单位)是紫色的。

最后修改日期是棕褐色的。

文件的名称是黑色的。

3 文件权限

4 文件权限

可以很容易地将权限设置视为一系列(计算机就是这样考虑它们的)。工作原理如下:

rwxrwxrwx = 111111111

rw-rw-rw- = 110110110

rwx------ = 111000000

| rwx=111,二进制 =7 | -wx=011,二进制 =3 |

| :--- | :--- |

| rw-=110,二进制 =6 | -w-=010,二进制 =2 |

| r-x=101,二进制 =5 | --x=001,二进制 =1 |

| r--=100,二进制 =4 | ---=000,二进制 =0 |

5 chmod (改变模式)

语法chmod [options] [mode] file...

| 参考 | 类别 | 描述 |

| :--- | :--- | :--- |

| u | 所有者 | 文件所有者 |

| g | | 属于该文件用户 |

| o | 其他 | 既不是文件所有者也不是该文件的成员的用户 |

| a | 所有 | 以上三者,等同于 ugo |

6 chmod

| 运算符 | 描述 |

| :--- | :--- |

| + | 将指定的模式添加到指定的类别 |

| - | 从指定的类别中删除指定的模式 |

| = | 指定的模式将成为指定类别的精确模式 |

7 chmod 示例

假设我们从以下开始:

-rwxr-xr-x user user header.sh

$ chmod g+w header.sh

-rwxrwxr-x user user header.sh

$ chmod o-x header.sh

-rwxrwxr-- user user header.sh

$ chmod 744 header.sh

-rwxr--r-- user user header.sh

8 硬链接 vs. 软链接 (符号链接)

9 硬链接 vs. 软链接 (符号链接)

10 硬链接

```

```

11 软链接

12 符号链接

lrwxrwxrwx 1 user user 11 Jan 23 14:49 shared -> /mnt/shared

注意文件类型是 'l'。

符号链接就像快捷方式target -> source

13 隐藏文件

14 隐藏文件以 . 开头。

要显示隐藏文件,请在 ls 命令中使用 -a 标志

| $ ls -a | | |

| :--- | :--- | :--- |

| . | .gnupg | shared |

| .. | .junk | .sudo_as_admin_successful |

| .bash_history | junk | Templates |

| .bash_logout | .lesshst | .vboxclient-clipboard.pid |

| .bashrc | .local | .vboxclient-display.pid |

| .cache | Music | .vboxclient-draganddrop.pid |

| .config | Pictures | .vboxclient-seamless.pid |

| Desktop | .profile | Videos |

| Documents | Public | .Xauthority |

| Downloads | .recyclebin | .xsession-errors |

15 Bash 入门

每个 bash 脚本的第一行必须是 #!/bin/bash 以调用 shell。这将在我们的 Linux 环境中工作。

您也可以使用:

16 #!/usr/bin/env bash

为了可移植性:不同的 *nix 系统将 bash 放在不同的位置,使用 /usr/bin/env 是一种运行 $PATH 中找到的第一个 bash变通方法

#! 称为 "shebang"。

这行必须出现在任何注释之前。

17 注释

18 注释以八进制字符 # 开头。

19 注释单行:

```

2Let this variable act as a boolean.

size_flag=0

```

20 用多个单行注释来注释多行:

```

####################################################################################################

3Name: parseargs.sh

4Author: Brian Borowski

5Last modified: May 23, 2025

6Description: bash script that shows how to work with getopts and arrays

####################################################################################################

```

21 变量

要设置变量,请写 =,如 count=0

要读取变量的值,请在其前面加上 $

echo "Count is $count."

读取 $ # 会告诉您提供给脚本命令行参数的数量。

假设您执行:./runme.sh A B C

$# 将等于 3。

22 Bash 中的数组

```

$ declare -a array

$ array[0]="hi"

$ array[1]="bye"

$ echo ${array[0]}

hi

$ echo ${array[1]}

bye

7Print all elements, separated by spaces. Treat each element as a separate word.

$ echo ${array[@]}

hi bye

8Print all elements as a single string, separated by spaces.

$ echo ${array[*]}

hi bye

$ echo ${#array[@]}

2

$ echo ${#array[*]}

2

```

23 Here Document

```

cat << ENDOFTEXT

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

ENDOFTEXT

```

作为多行字符串字面量非常有用,它保留了文本中的换行符和其他空白字符(包括缩进)。

24 在脚本中创建文件

```

loat << ENDOFTEXT

Lorem ipsum dolor sit amet, consectetur

adipiscing elit, sed do eiusmod tempor

incididunt ut labore et dolore magna

aliqua.

ENDOFTEXT

) > loremipsum.txt

```

脚本内部创建文本文件

25 使用 basename

```

$ basename /home/user/shared/sandbox/waterjugpuzzle.cpp

waterjugpuzzle.cpp

```

脚本中:

```

file="/home/user/shared/sandbox/waterjugpuzzle.cpp"

echo $(basename "$file")

... or ...

varname=$(basename "$file")

```

() 中调用命令会使用子 shell。要读取在子 shell中执行的程序的输出,请在 () 前面加上 $

26 基本条件语句

```

if [ ! -d "$dirname" ]; then # if directory doesn't exist

9do something

fi

if [ ! -f "$filename" ]; then # if file doesn't exist

10do something

fi

if [ $var -eq 1 ]; then # if variable's value equals 1

11do something

fi

```

另请参阅整数比较-ne-lt-gt-le-ge

字符串比较==!=

27 数学表达式

```

a=5

b=6

total=$(( a + b ))

echo $total

index=0

(( ++index )) # or

(( index++ )) # or

index=$(( index+1 )) # or

(( index=index+1 )) # or

(( index+=1 ))

echo $index

index is now 5

```

28 Bash 中的常量

我们可以通过将变量声明为 readonly 来使其成为 "常量"。在初始赋值之后,该变量不可更改。这对于在脚本的整个生命周期中其值应保持固定的全局变量非常有用。

```

$ readonly a=3

$ a=4

-bash: a: readonly variable

```

可以将变量可写更改为 readonly

```

$ b=3

$ readonly b=4

```

29 函数

要在 bash 中定义函数,请编写函数名开括号闭括号,以及开花括号闭花括号

```

myfunction() {

echo "Hello, world!"

}

```

参数位置的,从 $1 开始。如果您希望变量具有语义意义,请在函数内部重新分配它们。

```

myfunction() {

local name=$1

echo "Hello, $name!"

}

```

函数中,局部变量仅在该函数块内有意义。这是首选方法,这样您就不会无意中覆盖同名全局变量的值。

要调用函数,请使用任何参数调用函数名,每个参数之间用空格分隔。请务必用引号引起来包含空格字符串,以免它们被分成多个参数

myfunction "Dr. B"

30 使用命令行参数

您可以将参数传递给脚本

./myscript This is cool.

它们是位置的。在脚本内部,

```

$0: ./myscript

$1: This

$2 is

$3 cool.

```

31 引入 getopts

然而,有时我们可能需要解析标志,后跟位置参数,例如

./parseargs.sh -s a.txt b.txt getopts 内置于 bash 中,是一种方便的方法,用于解析所有标志(即那些带有短划线后跟字母选项),同时还以位置方式处理所有剩余参数

32 getopts

size_flag=0

while getopts ":s" option; do

33 getopts 示例

假设我们编写了一个名为 tail.sh脚本,仅打印文件 a.txtb.txtc.txt 的最后 -n 行。

假设我们再次抑制内部错误消息,为 getopts 编写 optstring

34 getopts 示例

假设我们编写了一个名为 tail.sh脚本,仅打印文件 a.txtb.txtc.txt 的最后 -n 行。

假设我们再次抑制内部错误消息,为 getopts 编写 opstring

答案:n:

我们还需要在 n 后面加上一个冒号,因为我们需要在命令行-n 之后立即检索用户提供的行数。

35 命令行参数索引

假设我们的 tail 脚本按如下方式调用

./tail.sh -n 5 a.txt b.txt c.txt

我们将得到以下命令行参数数组

| 1 | 1 | 2 | 3 | 4 | 5 |

| :--- | :--- | :--- | :--- | :--- | :--- |

| ./tail.sh | -n | 5 | a.txt | b.txt | c.txt |

OPTIND命令行下一个参数索引,在所有标志都用 getopts 解析后,所以 OPTIND 将是 3

# 显示从 $1` 开始的**(位置)参数**的数量。在这种情况下,打印 `$ # 显示 5

36 移位

| 0 | 1 | 2 | 3 | 4 | 5 |

| :--- | :--- | :--- | :--- | :--- | :--- |

| shift | -n | 5 | a.txt | b.txt | c.txt |

| 0 | 1 | 2 | 3 | 4 | 5 |

| ./tail.sh | a.txt | b.txt | c.txt | (空白) | (空白) |

37 移位后

您可以方便地遍历位置参数,如下所示:

```

for f in "$@"; do

echo "$f"

```

done

$@ 扩展为位置参数,从 1 开始。当在双引号内进行扩展时,每个参数扩展为单独的字符串

38 Shellcheck

shellcheck <您的脚本名称>,例如

shellcheck tail.sh