首页 > 系统相关 >Linux脚本学习笔记

Linux脚本学习笔记

时间:2022-12-29 17:23:42浏览次数:60  
标签:脚本 文件 链接 shell 笔记 echo Linux inode 目录

shell脚本

介绍

shell是一个命令解释器,它的作用是解释执行用户输入的命令或者程序

  1. 交互式的方式进行执行
  2. 非交互式的方式进行执行,通过shell脚本来执行

shell脚本的类型

shell脚本语言是弱类型语言,无需定义变量类型即可使用,Linux下主要有两种类型的shell语言

  • Bourne shell   包括Bourne shell(sh)、Korn shell(ksh)、Bourne again shell
  • C shell     包括csh, tcsh两种类型

查看系统默认的shell

echo $SHELL

查看系统支持的shell类型

cat /etc/shells

shell脚本执行

shell脚本的执行通常可以按照以下几种方式进行:

  • bash filename / sh filename   这种方式适用于脚本文件本身没有执行权限的时候
  • /path/filename         这种方式适用于脚本文件本身具有执行权限,则可以直接执行
  • source filename / .filename    通过这种方式读入和加载shell脚本文件,然后依次执行shell脚本中的语句,有区别的是,这些语句是在当前父shell脚本的进程中执行。其他两种方法都会启用新的进程执行该脚本。

shell脚本编写规范

遵循以下shell脚本规范,在提高开发效率的同时,降低后期的维护成本

  • 一个规范的shell脚本应该在第一行指出应该由哪个解释器来执行shell脚本中的内容,指定的方式为 #! /bin/bash 或者 #! /bin/sh , sh为bash的软连接,因此两者没有区别
  • ‘#’后面的内容表示注释内容,注释内容不会被执行,也不会被解释器看到
  • shell脚本的开头加版本,版权等信息
  • shell脚本文件的扩展名为 .sh
  • 成对的符号应尽量一次性写出来,然后退格在符号内增加内容,以防止遗漏。这些成对的符号包括: {}、[]、‘’、“” 等
  • 中括号[]两端至少要有1个空格,因此,键入中括号时即留出空格[ ],然后在退格键入中间内容,并确保两端都至少由一个空格
  • 对于流程控制语句,应一次性将格式写完,再添加内容

变量

  1. 变量的赋值方法为: 先写变量名称,紧接着是= ,最后是值。中间无任何空格。 通过echo命令加上 $变量名,即可输出变量的值

  2. 交互式赋值方法,将外部输入读取到变量中:

    read -p "Please input option: " Opt
    echo The user input is: $Opt
    

  3. 赋值时使用引号

    • 双引号 : 允许通过$符号引用其他变量的值
    • 单引号 : 不允许使用$符号引用其变量的值
    • 反引号 : 提取命令执行后的输出结果
    • $() 与 ``含义相同
    #! /bin/bash
    
    A=10
    echo $A
    
    # 无引号
    B=$A+10
    echo $B 
    
    # 双引号
    C="$A+10"
    echo $C
    
    # 单引号
    D=‘$A+10’
    echo $D
    
    E=`ls`
    echo $E
    
    F=$(ls)
    echo ${F}    # 同$F
    

  4. 位置参数

    位置参数是一种在调用shell程序的命令中按照各自的位置决定的变量,是在shell脚本之后输入的参数。位置参数之间使用空格进行分割,shell取第一个位置参数的值赋给shell脚本中的$1,第二个位置参数的值赋给$2,以此类推。$0是一个特殊变量,其内容为当前shell脚本的文件名,所以$0不是一个位置参数。

    #! /bin/bash
    
    # $# 是一个预定义变量,表示位置参数的数量
    
    echo The para count is: $#
    
    echo The bash script name is: $0
    
    echo The first pos para is: $1
    
    echo The second pos para is: $2
    

  5. 预定义变量

    预定义变量是在shell脚本一开始就定义的变量,shell脚本预定义了若干个变量供用户使用,所有的预定义变量都由$和另一个字符构成。常见的shell预定义变量如下所是:

    预定义变量 含义
    $# 位置参数数量  
    $* 所有位置参数的内容
    $? 命令执行后的返回状态  0:正常  1:错误
    $$ 当前进程的进程号
    $! 后台运行的最后一个进程号
    $0 当前执行的进程名 (shell程序的文件名)
    $@ 传递给脚本或者函数的所有参数内容
    示例代码
    #! /bin/bash
    
    echo "Current file name: $0"
    
    echo "First Para is : $1"
    
    echo "Second Para is : $2"
    
    echo "Inputed Para1: $@"
    
    echo "Inputed Para2: $*"
    
    echo "Total Parameter number: $#"
    
    echo "Current process id is: $$"
    
    exit 1
    

    Note
    $* 和 $@ 都表示传递给函数或者脚本的所有参数,不被双引号包含时,都以"$1","$2","$3"...的形式输出所有参数。当被双引号包围时,"$*"会将所有的参数作为一个整体输出,以"$1 $2 $3 ... $n"的形式进行输出。"$@"会将各个参数分开,以"$1" "$2" "$3" ... "$n"的形式输出所有参数。

    示例代码
     #! /bin/bash
    
     # 无双引号
     echo "\$*="$*
    
     # 有双引号
     echo "\"\$*\"=""$*"
    
     # 无双引号
     echo "\$@="$@
    
     # 有双引号
     echo "\"\$@\"=""$@"
    
     # 循环输出
     echo "Print each param in \$@"
     for var in $@
     do 
         echo var is: $var
     done
    
     echo "Print each param in \"\$@\""
     for var in "$@"
     do 
         echo var is: $var
     done
    
     echo "Print each param in \$*"
     for var in $*
     do 
         echo var is: $var
     done
    
     echo "Print each param in \"\$*\""
     for var in "$*"
     do 
         echo var is: $var
     done
    
    

条件判断

测试表达式

  在shell的各种条件结构和流程控制结构中都要进行各种测试,然后根据测试结果的不同执行不同的分支,通常会与if等条件语句相结合,来完成测试判断,减少程序执行错误。

几种条件测试语法
  • test 测试表达式
  • [ 测试表达式 ]
  • [ [ 测试表达式 ] ]
  • ((测试表达式))
条件测试语法比较
test [ ] [ [ ] ] (())
边界是否需要空格 需要 需要 需要 不需要
逻辑操作符 !   -a   -o !   -a   -o !   &&   || !   &&   ||
整数比较操作 -eq -gt -lt -ge -le -eq -gt -lt -ge -le -eq -gt -lt -ge -le
或 = > >= < <=
-eq -gt -lt -ge -le
或 = > >= < <=
字符串比较操作 =   ==   != =   ==   != =   ==   != 不支持
文件操作 -d -f -e -s -r -x -w L
-nt -ot
-d -f -e -s -r -x -w L
-nt -ot
-d -f -e -s -r -x -w L
-nt -ot
不支持
是否支持通配符匹配 不支持 不支持 不支持 不支持
文件测试操作符
文件测试操作符 说明
-d 文件存在且类型为目录,返回真
-f 文件存在且类型为文件,返回真
-e 文件存在返回真
-s 文件存在且大小不为0,返回真
-r 文件存在且可读,返回真
-w 文件存在且可写返回真
-x 文件存在且可执行,返回真
-L 文件存在且为链接文件,返回真
f1 -nt f2 文件f1比文件f2新,返回真
f1 -ot f2 文件f1比文件f2旧,返回真
test 示例代码

#! /bin/bash

echo "Test the file myfile.txt.\n"

if test -e ./myfile.txt ; then              # 文件存在
    echo "File \"myfile.txt\" exist.\n"
    
    if test -d ./myfile.txt ; then          # 是否为目录
        echo "File \"myfile.txt\" is a directory.\n"
    else
        echo "File \"myfile.txt\" is file.\n"

        if test -r ./myfile.txt -a -w ./myfile.txt ; then       # 可读 且 可写
            echo "File \"myfile.txt\" can read and write.\n"
        elif test -x ./myfile.txt ; then                        # 可执行
            echo "File \"myfile.txt\" can execute.\n" 
        else
            echo "File \"myfile.txt\" can not both read and write and execute.\n"
        fi
    fi
else
    echo "File \"myfile.txt\" not exist.\n"
fi

输出:

[ ]示例代码

#! /bin/bash

echo "Test the file myfile.txt.\n"

if [ -e ./myfile.txt ] ; then              # 文件存在
    echo "File \"myfile.txt\" exist.\n"
    
    if [ -d ./myfile.txt ] ; then           # 是否为目录
        echo "File \"myfile.txt\" is a directory.\n"
    else
        echo "File \"myfile.txt\" is file.\n"

        if [ -r ./myfile.txt ] && [ -w ./myfile.txt ] ; then       # 可读 且 可写
            echo "File \"myfile.txt\" can read and write.\n"
        elif [ -x ./myfile.txt ] ; then                        # 可执行
            echo "File \"myfile.txt\" can execute.\n" 
        else
            echo "File \"myfile.txt\" can not both read and write and execute.\n"
        fi
    fi
else
    echo "File \"myfile.txt\" not exist.\n"
fi

字符串测试操作符
常用字符串测试操作符 说明
-n 若字符串长度不为0,返回真
-z 若字符串为空,返回真
str1 == str2 字符串相等
str1 != str2 字符串不相等

note : == 和 !=两端都要有空格


#! /bin/bash

str1="hello"
str2="world"

# test 判断
if test -z $str1 -o -z $str2 ; then
   echo "str1 or st2 is empty.\n"
else
   if test $str1 == $str2 ; then
      echo "str1 equals to str2.\n"
   else
      echo "str1 not equals to str2.\n"
   fi
fi

# [] 判断
if [ -z $str1 ] || [ -z $str2 ] ; then
    echo "str1 or st2 is empty.\n"
else
    if [ $str1 == $str2 ] ; then
        echo "str1 equals to str2.\n"
    else
        echo "str1 not equals to str2.\n"
    fi
fi

比较运算符 (整数比较)
表示方法1 表示方法2
-gt >
-ge >=
-lt <
-le <=
-eq ==

#! /bin/bash

var1=3
var2=4

if test 3 >= 4 ; then
   echo "var1 equals to var2.\n"
else
   echo "var1 not equals to var2"
fi

逻辑运算
表示方法1 表示方法2 说明
-a &&
-o ||
! !
case条件判断语句

  case条件语句相当于if多分支语句,但是其格式更加的工整规范,适合实现系统服务启动脚本应用

```bash

#! /bin/bash

read -n1 -p "Are you sure to start the routine(y or n) ?" choice

echo     # 换行

case $choice in
    [yY])                               # y or Y
    echo "Starting the routine."        # 会自动换行
    ;;
    "n" | "N")                          # n or N
    echo "Exiting the routine."
    ;;
    *)                                 # 相当于default
    echo "Unexpected input."
esac


read -n1 -p "Please input content(char): " content

echo 

case $content in
    [a-z])                               # 范围a-z
    echo "Lower case letter."
    ;;
    [A-Z])
    echo "Uper case letter."
    ;;
    [0-9])
    echo "number."
    ;;
    *)
    echo "Unknown content"
esac

```

循环

数组

  在shell脚本中,采用括号来定义数组,数组元素使用空格隔开


#! /bin/bash

# 数组定义
array=(1  2 3 4 5)

array1[0]=1
array1[1]=1
array1[2]=1
array1[3]=1

# 读取数组元素
ele=${array[0]}
echo -e "First element in array is $ele"    # 添加 -e可实现换行    \c表示不换行

# 获取数组长度
len=${#array[@]}      # 等效于 ${#array[*]}

# 获取特定元素的长度
eleLen=${#array[0]}

echo Array length is: $len

echo Element len is: $eleLen

# 数组遍历 (不带下标)
for var in ${array[@]} ; do
    echo Value: $var
done

array2=("Hello" "world" "test" "thus")
# 数组遍历 (带下标)
for((i=0; i<${#array2[@]};i++)); do
    echo Value is: ${array2[i]}

    if test $i -eq 1 ; then
        echo "Element length is ${#array2[i]}"
    fi
done

for语法格式
for 条件 
do
    命令
done

# 或者

for 条件 ; do
    命令
done
while循环

while 条件
do 
    命令
done
循环控制语句
命令 说明
break n n表示跳出循环的层数,如果省略,则表示跳出整个循环
continue n n表示退到第n层循环继续,如果省略,则表示跳过本次循环
exit n 推出当前shell程序,n为上一次执行的返回值,在下一个shell里面可以通过$?接收n的指

示例代码

#! /bin/bash

# 单层break
while true ; do
    read -n1 -p "Please input a number: " number

    echo

    case $number in
        [0-9])
        echo You input a number: $number
        ;;
        *)
        echo It is not a number.
        break                         # 也可修改为continue
        ;;                            # note 可写可不写
    esac
done

# 多层break
for var1 in 1 2 3 ; do
    for var2 in 7 8 9 ; do
        if [ $var1 -eq 3 -a $var2 -eq 9 ] ; then
            break 2          # 跳出两层循环
        else
            echo -e "Result: $var1 + $var2 \n"
        fi 
    done
done

函数

与其他编程语言一样,shell脚本也支持函数,函数必须线定义再使用

函数的定义格式如下所示:


func_name () {
    command1
    command2
    ...
    [return value]
}

函数的返回值为return语句返回的指,如果没有return语句,则会将最后一条命令执行的结果作为返回值。且shell函数的返回值只能是整数,一般用来表示执行成功与否,0表示成功,其他值表示失败。如果return了其他的数据类型,比如字符串,则会出现错误提示:"numeric argument required".

如果需要返回字符串,可以在函数外预先定义一个字符串变量,在函数中用来接收函数的执行结果,在函数执行完成之后,再去访问预先定义的变量,获取函数的执行结果

#! /bin/bash

# define function 
hello () {
    echo -e "Hellow everyone."
}

# invoke function
hello

带有返回值的函数

#! /bin/bash

# 定义函数
funcSum () {
    read -p "Please input one number: " num1
    read -p "Please input another number: " num2

    return $(($num1 + $num2))
}

# 调用函数
funcSum

# 获取函数调用返回值
ret=$?

echo Sum is: $ret

函数传参

在shell脚本调用函数的时候,可以向其传递参数,在函数内部可通过$n的指来获取参数的值,注意当n>=10的时候,需要通过${n}来获取参数的值.


#! /bin/bash

funcPara () {
    # 参数
    echo "Para 0 is: $0"      # 脚本文件的文件名
    echo "Para 1 is: $1"
    echo "Para 2 is: $2"
    echo "Para 3 is: $3"

    # 获取所有参数
    echo "All para are: $*"
}

funcPara 1 2 3 4

note

unset除了可以删除变量,也可以删除函数,删除函数的时候需要加上.f选项(unset具体使用见后续Linux命令):

$unset .f funcName

此外,如果需要直接从终端调用函数,可以将函数定义在主目录下的.profile文件中,每次登陆后,在命令提示父后面可直接调用函数

输入输出重定向

Unix命令默认从标准输入(stdin)设备获取输入,将结果输出到标准输(stdout)出设备。

输出重定向

命令的输出不仅可以是标准输出,还可以将其转移向文件,这被称为输出重定向,输出重定向的语法为

command > filename

输出重定向会覆盖文件原有的内容,如果希望文件内容不被覆盖,可按照如下方法将输出内容追加到文件末尾


command >> filename
command >> filename
...
输入重定向

类似于输出重定向,Unix命令也可以从文件获取输入,语法为

command < file

重定向之后,本来需要从键盘获取输入的命令会转移到文件读取内容,例如统计某文件的行数:

 wc -l < filename
补充内容

一般情况下,每个Linux命令运行,都会打开以下三个文件:

  • 标准输入文件(stdin)    stdin文件的文件描述符为0,Linux命令默认从stdin读取数据
  • 标准输出文件(stdout)    stdout文件的文件描述符为1,Linux命令默认向stdout输出数据
  • 标准错误文件(stderr)    stderr文件的文件描述符为2,Linux命令默认向stderr写入错误信息

如果希望将stderr重定义到文件,可采用如下的方法:

 command 2>file
 command 2>>file      # 追加

如果希望将标准输出和标准错误输出合并到同一个文件,可采用如下的方法


 # 文件描述符1和文件描述符2合并,重定向到文件输出
 command > file 2>&1
 command >> file 2>&1

 # 读如也可以采取合并

 # n <& m 将输入文件m和n进行合并
/dev/null文件

在执行某个命令的时候,如果希望不再屏幕上显示输出结果,可以将输出结果重定向到/dev/null,这是一个特殊的文件,写入这个文件的内容都会被丢弃,如果从该文件读取内容,将读取不到任何内容。可以将输出重定向到这个文件,起到禁止命令执行结果输出的效果。

 
 command>/dev/null 2>&1

xargs参数过滤

xargs (extended arguments)是给命令传递参数的一个过滤器,也是组合多个命令的一个工具,


Linux常用命令

read命令

Linux read命令用于从标准输入读取数值,当使用重定向的时候,可以读取文件中的一行数据

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
参数说明
  • -a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符
  • -d 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志(作为什么结束的标志?)
  • -p 后面跟提示信息,即在输入前打印提示信息
  • -e 在输入的时候可以使用命令补全功能
  • -n 后跟一个数字,定义输入文本的长度,当输入计数到定义的长度后,读取自动停止
  • -r 屏蔽\,如果没有该选项,则\作为一个转义字符,有的话 \就是个正常的字符了
  • -s 安静模式,在输入字符时不再屏幕上显示,例如login时输入密码
  • -t 后面跟秒数,定义输入字符的等待时间
  • -u 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的
示例代码
#! /bin/bash

# -p参数
read -p "Please input option: " Opt
echo The user input is: $Opt

# -d参数
read -de cm            # 将输入读取到变量cm中,碰到字符e则停止读取(读取结果不包含e),无需按回车
echo                   # 换行
echo The user input is: $cm

# -n参数
read -n5 -p "Please input your name: " name  # 限定长度为5,读取计数到5自动结束
echo                   # 换行 自动结束的需要添加换行
echo The user name is: $name

# -s参数
read -s -p "Please input code: " code
echo The code is: $code

# -t参数
if read -t3 -p "Please input content: " content ; then
     echo The content is : $content
else
     echo You has expired!
fi

echo命令

echo命令用于字符串输出

echo content      # 会默认换行

参数:

  • -e  开启转义,打印出转义字符
  • -n  去掉echo末尾默认的换行符
示例代码
echo This is a test str

echo "This is a test str"

echo \"This is a test str\"

echo "\"This is a test str\""

echo "This is a test \n"

#换行 -e开启转义,实现换行 \n
echo -e "This is a test \n" 

# 不换行 -e开启转义,实现不换行 \c
echo -e "This is a test \c"
echo "Continue"

# 显示执行结果
echo `date`

# 显示结果定向至文件
echo "This is a test.\n" > myfile.txt

file命令

file命令主要用于辨识文件的类型

file [-bcLvz][-f <名称文件>][-m <魔法数字文件>...][文件或目录...]

参数含义

  • -b  列出辨识结果时,不显示文件名
  • -c  详细显示指令的执行过程,便于分析程序执行情形
  • -f  指定文件名称,当有一个或者多个文件名称的时候,让file依次辨识这些文件
  • -L  显示链接符号所指向的文件的类型
  • -m  制定魔法数字文件
  • -v  显示版本信息
  • -z  尝试去解读压缩文件的内容
  • [文件或目录列表]  要确定类型的文件列表,多个文件之间使用空格分隔开来,可使用shell通配符来匹配多个文件
示例代码

#! /bin/bash

# 获取当前目录
cur_dir=$(pwd)

script_path=$cur_dir/demonscript4.sh

file $script_path

file -b $script_path

file -i $script_path

file -i -b $script_path

不同文件类型的魔术数字(附加)

  文件类型的魔术数字,指定是文件的最开头的几个用于唯一区别其它文件类型的字节,有了这些魔术数字,我们就可以很方便的区别不同的文件,这是除了后缀名区分文件类型的另一种区分文件类型的方法。例如,对于一个JPEG文件,开头的可能是“ffd8 ffe0 0010 4a46 4946 0001 0101 0047 ……JFIF…..G”之类的字符,"ffd8"就表示这个文件是一个JPEG类型的文件,"ffe0"表示这个文件是一个JFIF结构,以下列出几种常见文件类型的魔术数字以及对应的ASCII字符:

文件类型 后缀名 魔术数字 ASCII字符
Bitmap Format .bmp  42 4d BM
GIF Format .gif  47 49 46 38 GIF8
JPEG File Interchange Format .jpg  ff d8 ff e0 ....
PNG format .png  89 50 4e 47 .PNG
pkzip format .zip  50 4b 03 04 PK..

获取当前shell脚本所在的路径

介绍两种shell脚本中获取脚本文件所在路径的方法

#! /bin/bash

# 方法1 获取当前目录
cur_dir=$(pwd)

# 方法2 获取当前目录
cur_dir=`cd $(dirname $0); pwd`

# dirname $0,取得当前执行的脚本文件的父目录 pwd 显示当前工作目录

cut 命令

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出,如果没有指定file参数,cut命令将读取标准输入,显示每行从头开始算起num1到num2的文字,语法如下所示:


 cut  [-bn] [file]
 cut [-c] [file]
 cut [-df] [file]

参数含义

  • -b  以字节为单位进行分割,这些字节位置将忽略多字节边界符,除非指定了-n参数
  • -c  以字符为单位进行分割
  • -d  自定义分割符,默认为制表符
  • -f  提取指定的字段
  • -n  取消分割多字节字符,仅仅和-b一起配合使用

unset命令

unset命令用于删除已定义的变量(shell变量或者环境变量),或者shell函数

unset [-fv][变量或函数名称]

参数含义

  • -f  仅删除函数
  • -v  仅删除变量
export usernametest=ubantu_all    # 定义环境变量

echo $usernamett                    # 查看环境变量

unset usernamett                    # 删除环境变量

zip命令

zip压缩文件

.zip格式是windows和Linux通用的压缩文件格式,命令的基本格式如下

zip [-AcdDfFghjJKlLmoqrSTuvVwXyz$][-b <工作目录>][-ll][-n <字尾字符串>][-t <日期时间>][-<压缩效率>][压缩文件][文件...][-i <范本样式>][-x <范本样式>]

参数含义(常用几个参数)

  • -r  递归压缩目录
  • -m  压缩完成后,删除原始的文件
  • -v  显示压缩的详细过程
  • -q  压缩的时候不显示命令的执行过程
  • -n  n取(1-9),压缩级别,1代表压缩速度更快,9代表压缩效果更好
  • -u  更新压缩文件,即往压缩文件中添加新文件

示例代码

#! /bin/bash

# 获取当前脚本路径
cur_dir=`cd $(dirname $0); pwd`

echo "Current script path is $cur_dir"

filenames=test    # 文件名

filecount=4       # 文件个数

fileSuffix=.txt   # 文件后缀名

# 数组
files=()

for((i=0;i<$filecount;i++)); do
    index=$(($i+1))
    #let index=$i+1             # i+1等效写法
    #index=`expr $i + 1`        # i+1等效写法
    filenamepath=${cur_dir}/${filenames}${index}${fileSuffix}

    if [ -e $filenamepath -a -f $filenamepath ]; then
        rm -f $filenamepath

        if [ $? -eq 0 ]; then
            echo "Success delete file \"$filenamepath\""    # 删除成功,给出提示
        fi
    fi

    touch $filenamepath
    
    if test $? -eq 0 ; then        # 获取touch命令的执行结果,0 成功
        echo "Success created file \"$filenamepath\"" >> $filenamepath
    fi

    # 文件名保存在数组中
    files[$i]=$filenamepath

done

# 压缩文件的个数  求取数组长度
filescount=${#files[@]}

echo "Total $filescount file(s) to be compressed."

for((i=0;i<$filescount;i++)); do
    filename=${files[i]}
    
    #let fileindex=$i+1
    #if [ $fileindex -ge 3 ] ; then
    #    break
    #fi

    echo "zipping file \"$filename\""

    if test $i -eq 0 ; then
        zip -2 test.zip $filename
        continue
    fi

    zip -u -2 test.zip ${filename}     # 所有文件压缩 
done

echo "------End-----"
unzip命令解压文件

unzip命令用于解压.zip压缩文件

unzip [-cflptuvz][-agCjLMnoqsVX][-P <密码>][.zip文件][文件][-d <目录>][-x <文件>] 或 unzip [-Z]

参数含义

  • -d   将压缩文件解压到指定目录下 unzip -d dirname *.zip
  • -n   解压时不覆盖已存在的文件
  • -o   解压时覆盖已存在的文件,且无需用户确认
  • -v   查看压缩文件的详细信息,包括压缩文件中包含的文件大小、文件名以及压缩比等,但并不做解压操作
  • -t   测试压缩文件是否损坏,但是不解压文件
  • -x   解压文件,但是-x指定的文件会跳过,不进行解压

示例代码

#! /bin/bash

unzip -d ./unzipdir ./test.zip      # 指定解压目录

unzip ./test.zip -x file1 file2     # 不解压file1 file2

cp命令

cp命令用于将一个或者多个文件,或者目录复制到指定位置,也可用于文件的备份

参数含义

  • -f  若目标文件已经存在,则会直接将目标文件进行覆盖
  • -i  若目标文件已经存在,则会询问是否进行覆盖
  • -p  保留源文件或者源目录的所有属性
  • -r  递归复制,用于文件夹拷贝
  • -b  覆盖已存在的目标文件时,将目标文件进行备份
  • -v  详细显示cp命令执行的操作过程
  • -d  当复制符号链接的时候,把目标文件或者目录也建立为符号链接,并将其指向源文件或者元目录所连接的文件或者目录
  • -l  对源文件建立硬连接,而非复制文件
  • -s  对源文件建立软连接,而非复制文件
  • -a  等价于-pdr

find命令

find命令是Linux中强大的搜索命令,可以按照文件名,文件权限,文件大小,时间,inode号等信息搜索文件,因为find命令是直接在硬盘中进行搜索,因此对其指定合适的搜索范围特别重要,如果搜索的范围过大,就会导致消耗较大的系统资源。

命令格式:

find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;

path :  搜索路径
option :  搜索选项

选项

  • -name  按照文件名进行搜索
  • -iname  按照文件名进行搜索,不区分大小写
  • -inum  按照inode号进行搜索
  • -size[+-]  按照文件大小进行搜索, +表示大于size的文件,-表示小于size的文件,(M, k)
  • -type  按照特定的类型查找文件, d-目录 f-一般文件 l-符号链接 s-套接字文件 c-字符设备 b-块设备
  • -print   将搜索结果输出到标准输出
  • -ctime  按照文件创建时间进行搜索 [+-n]
  • -mtime  按照文件更改时间进行搜索 [+-n]
  • -atime  按照文件访问时间进行搜索 [+-n]
  • -perm  按照文件权限进行搜索

按照文件类型搜索,可选的文件类型如下所示

符号 含义
d  搜索目录
f  搜索一般文件
l  搜索链接文件
s  搜索套接字文件
c  搜索字符设备文件
b  搜索块设备文件

按照文件大小搜索,表示文件大小的可选单位如下所示:

符号 含义
b   块 512字节
c  字节
w  字
k  千字节
M  兆字节
G  吉字节

按照修改时间,创建时间,访问时间进行修改,指定时间时可通过+-来指定特定范围的时间,具体使用方式如下所示:

符号 含义
-n 表示从当前时间算起,n天以内
n 表示从当前时间算起,第n年
+n 表示从当前时间算起,第n天以前

示例代码

find ./ -name "*.txt"    # 查找后缀名为.txt的文件
find ./ -type f          # 查找普通文件


Linux

Linux系统目录结构

  在Linux或者Unix系统中,所有文件和目录都被组织成以一个根节点开始的树状结构,文件系统的最顶层是由根目录开始\,根目录下既可以是文件。如果一个目录或者文件是以.开头的,则表示这个文件或目录是隐藏的。系统目录结构如下所示:

目录具体含义:

  • /bin  Binaries(二进制文件)的缩写,存放着最经常使用的命令
  • /boot  用于存放启动Linux时所需要的一些核心文件,包括一些链接文件以及镜像文件
  • /dev  Devices的缩写,用于存放Linux的外部设备,在Linux中设备也是以文件的形式进行表示的,访问设备的方式与访问文件的方式类似。
  • /etc  Etcetera(等等)的缩写,用来存放所有系统管理所需要的配置文件和子目录
  • /home  用户的主目录,在Linux中,每个用户都有一个自己的目录,一般是以用户的账号进行命名的,如上途中的alice,bob等
  • /lib  Library(库)的缩写,这个目录存放着系统最基本的动态链接共享库,几乎所有的应用程序都会用到这些共享库
  • /lost+found  这个目录一般是空的,当系统非法关闭后,会暂时保存一些文件
  • /media  Linux系统会自动识别一些设备(u盘,光驱),识别到后会将这些设备自动挂载此目录下
  • /mnt  系统提供该目录是为了让用户临时挂载别的文件系统,例如光驱或者u盘
  • /opt  存放其他需要额外安装的软件
  • /proc  Process(进程)的缩写,/proc是一种伪文件系统(即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,这个目录是一个虚拟目录,可以通过直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上,而是在内存里面。可以通过直接修改里面的某些文件,来实现对系统的设置,例如,可以向特定的文件写入内容,来实现屏蔽主机的ping命令:
    echo 1 /proc/sys/net/ipv4/icmp_echo_ignore_all,向这个文件写入1,就可实现屏蔽ping命令,使得其他主机无法ping到当前主机。
  • /root  为系统管理员的用户目录
  • /selinux  这个目录是 Redhat/CentOS 所特有的目录,Selinux 是一个安全机制,类似于 windows 的防火墙,这个目录存放selinux相关的文件。
  • /sys 这是Linux2.6内核的一个重大变化,该目录下安装了2.6内核中新出现的一个文件系统sysfs,sysfs文件系统集成了以下三种文件系统的信息:
    1. 针对进程信息的proc文件系统
    2. 针对设备的devfs文件系统
    3. 针对伪终端的devpts文件系统
  • /tmp  Temporary的所缩写,用来存放一些临时文件
  • /usr  Unix Shared Resources, 共享资源目录,用户的很多应用程序和文件都存放在这个目录下,相当于Windows的Program Files目录
  • /usr/bin  系统用户使用的应用程序
  • /usr/src  内核源代码默认的放置目录
  • /var  Variable缩写,这个目录存放着不断扩充的东西,通常会将经常被修改的目录或者文件存在这里,例如日至文件
  • /run  是一个临时文件系统,存储系统启动以来的信息,当系统重启的时候,这个目录下的文件应该被删掉或清除。

软链接与硬链接

  Linux文件系统中,数据分为元数据和用户数据,用户数据,即文件数据块(data block)是记录文件真实内容的地方。元数据是文件的附加属性,记录了如文件大小,创建时间,属主,inode(索引节点,为一个结构体)等信息。在Linux文件系统中,文件名并不是文件的唯一标识,元数据中的inode号才是文件的唯一标识。为解决文件的共享使用问题,Linux引入了应链接和软链接的概念,通过链接,隐藏了源文件的路径,提升了权限安全以及节省了内存。
  文件名只是为了方便区分和记忆,在Linux文件系统中,系统和程序是通过inode号来寻找正确的文件数据块,通过文件名获取文件内容的过程如下:

   filename-->inode-->data block

  在Linux中,可通过ls -i filename来查看文件的inode号,可以通过stat filename查看文件的inode信息

硬链接

  若一个inode号对应多个文件名,则城这些文件为硬链接,硬链接是指一个文件使用了多个别名,但是这些文件都具有相同的inode号。

特点:

  • 所有文件具有相同的inode号以及data block
  • 只能对已经存在的文件创建硬链接
  • 不能对目录创建硬链接
  • 不能交叉文件系统创建硬链接(因为inode号只在各文件系统下是唯一的,当Linux系统下挂载了多个文件系统后,可能出现inode号重复)
  • 删除一个硬链接并不影响其他的硬链接

  可以使用命令df -i --print-type来查看当前系统中挂载的文件系统类型,各文件系统使用情况以及文件系统挂载点等信息。

软链接

若文件的用户数据快中存放的是另一个文件的路径指向,则该文件就称为软链接,因此软链接本质上就是一个文件,只是文件的内容比较特殊,软链接有自己的inode号以及用户数据,因此软链接的创建和锁定和使用限制较少。

特点:

  • 软链接有自己的文件权限及属性
  • 可对不存在的文件或者目录创建软链接
  • 软链接可交叉文件系统进行创建
  • 删除软链接并不影响被指向的文件。若被指向的文件被删除,则相关的软链接称为死链接(dangling link),若被指向的文件被重建,则死链接可恢复为正常的链接
链接的创建
ln -s filename softlink      # 建立软链接
ln filename hadrlink         # 建立硬链接

cp -s filename softlink      # 建立软链接
cp -l filename hardlink      # 建立硬链接

文件存储-关于inode补充
  文件存储在硬盘上,硬盘的最小存储单位叫做扇区(sector),每个扇区存储512个字节,操作系统在读取硬盘的时候,不会一个扇区一个扇区的读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个块(Block),这种由多个扇区组成的块,是文件存取的最小单位,块的大小,最常见的是4kB,即8个连续的扇区组成一个快。文件数据都存储在块中,那么,还必须找到一个地方存储文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。
  inode包含文件的元信息,具体来说有如下内容:

  1. 文件的字节数
  2. 文件拥有者的user id
  3. 文件的group id
  4. 文件的 r w x 权限
  5. 文件的时间戳,ctime表示inode上一次变动的时间,mtime表示文件内容上一次的变动时间,atime表示文件上一次打开的时间
  6. 文件数据Block的位置

  inode也会占用硬盘的空间,因此在硬盘格式化的时候,操作系统会自动将硬盘分为两个区域,一个是数据区,用于存放所有的文件数据;另一个是inode区(inode table),用于存放inode所包含的信息。每个inode的大小为128或者256个字节,inode节点的总数,在格式化的时候就已经给定,一般是1kB或者2kB就设置一个inode。假定在一块1G的硬盘中,每个inode节点的大小为128字节,每1KB设置一个inode,那么inode table的大小就会达到128M,占据整块硬盘容量的12.8%,可以使用df -i查看每个硬盘下的inode总数以及使用情况(可以看到每个硬盘下的inode总数,以使用的inode数量,未使用的inode数量等信息)

每个文家都必须有一个inode,因此可能会发生inode已经用光,但是硬盘还未满的情况,此时也是无法进行文件创建的

目录文件:

在Linux系统中,目录也是一种文件,打开目录,实际上就是打开目录文件,目录文件的结构较为简单,其内容是由一些列目录项构成的目录列表,每个目录项由两部分构成,该目录下文件的文件名,以及文件名所对应的inode号。由ls -i dir可查看特定目录下的所有目录项。

目录文件的链接数:

创建文件的时候,默认生成两个目录项...,.相当于当前目录文件的硬链接,而..相当于当前目录父目录的硬链接,因此,任何一个目录的硬链接总数,等于2加上它的子目录总数,这里的2是父目录对其的“硬链接”和当前目录下.对其的硬链接

Linux文件类型

Linux常见的文件类型有七种:

表示符号 文件类型 补充
- 常规文件 即file
d 目录文件 目录
b 块设备文件 Block Device 文件,如硬盘,支持以Block为单位进行随机访问
c 字符设备文件 Character Device 文件,如键盘支持以字符为单位进行线性访问
l 符号链接文件 Symbol Link 软链接文件
p 管道文件 pipe文件
s 套接字文件 socket文件

对于普通文件,ls -l会显示文件的大小,但是在设备类文件中,会显示两个用逗号隔开的数字,这两个数字不表示文件的大小。第一个数字表示主设备号,第二个数字表示次设备号,主设备号用于区分设备类型,用于决定加载设备的驱动程序。次设备号用于区分同一类型的不同设备,如硬盘1,硬盘2

文件基本属性

参考网址

Email: [email protected] 测试
web: www.baidu.com

ceshi

标签:脚本,文件,链接,shell,笔记,echo,Linux,inode,目录
From: https://www.cnblogs.com/ncepubye/p/17013021.html

相关文章

  • linux 在本地对远程仓库执行git pull
    linux在本地对远程仓库执行gitpull假设:你的同事在Linux主机A上生成了一个git仓库S用来维护一堆配置文件,配置文件会经常发生变动。你编写了一个脚本并在Linux主机B上执行......
  • 实战练习:用airtest-selenium脚本爬取百度热搜标题
    1.前言很多同学,使用AirtestIDE都是做移动端的测试,其实它还有个隐藏功能,就是做web自动化测试。搞网页测试,使用AirtestIDE的好处是,能借助selenium的辅助窗,帮助我们快捷地......
  • linux跟踪技术之ebpf
    ebpf简介eBPF是一项革命性的技术,起源于Linux内核,可以在操作系统内核等特权上下文中运行沙盒程序。它可以安全有效地扩展内核的功能,而无需更改内核源代码或加载内核模块......
  • CH9434-MCU代码移植,芯片使用详细说明(附Linux开发资料链接)
    简介CH9434是一款SPI转四串口转接芯片,提供四组全双工的9线异步串口,用于单片机/嵌入式/安卓系统扩展异步串口。提供25路GPIO,以及支持RS485收发控制引脚TNOW。本篇基于STM32......
  • Linux 的 top 命令平均负载
    每次发现系统变慢时,我们通常做的第一件事就是使用​​uptime​​​或​​top​​命令查看系统的“平均负载”[root@rocketmq-n2~]#uptime11:33:53up2:18,2user......
  • Linux常用操作
    1、linux环境变量​​参考:Linux下设置和查看环境变量​​(1)、在/etc/profile文件中添加变量,对所有用户生效(永久的)(2)、在用户目录下的.bash_profile文件中增加变量【对单一用......
  • Linux 输出日期时间
    年月日echo$(date+%F) //2020-12-30echo$(date+%Y/%m/%d) //2020/12/30;%Y:年|%m:月|%d:日时分echo$(date+%R) //10:00时分秒echo$(date+%T) ......
  • 关于DASH直播实现的笔记
    1.dash是什么关于介绍百度一下就好了,以下是相关介绍https://it3q.com/article/782.关于dash的开源代码https://github.com/ireader/media-server我参照的相关例子是......
  • F5 Big-IP真实内网IP泄露Python3计算脚本
    漏洞描述:F5BIG-IP是美国F5公司一款集成流量管理、DNS、出入站规则、web应用防火墙、web网关、负载均衡等功能的应用交付平台。F5Big-IP可以解码cookie,获取内网真实IP。......
  • Web前端学习笔记2——表格
    表格的基本语法以及标签表格示例1:table标签就是表格的标签,用来建立一个表格tr标签表示行,一个<tr></tr>标签就是一行td标签表示数据单元格的内容,可以理解为列th标签为......