编写脚本实现在指定文件路径下查找文件夹或文件名。
 
脚本如下:
#!/bin/sh
# lazy find # GNU All-Permissive License
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved. This file is offered as-is,
# without any warranty. ## help function function helpu {
echo " "
echo "Fuzzy search for filename."
echo "$0 [--match-case|--path] filename"
echo " "
exit
} ## set variables MATCH="-iname"
SEARCH="." ## parse options while [ True ]; do
if [ "$1" = "--help" -o "$1" = "-h" ]; then
helpu
elif [ "$1" = "--match-case" -o "$1" = "-m" ]; then
MATCH="-name"
shift 1
elif [ "$1" = "--path" -o "$1" = "-p" ]; then
SEARCH="${2}"
shift 2
else
break
fi
done ## sanitize input filenames
## create array, retain spaces ARG=( "${@}" )
set -e ## catch obvious input error if [ "X$ARG" = "X" ]; then
helpu
fi ## perform search for query in ${ARG[*]}; do
/usr/bin/find "${SEARCH}" "${MATCH}" "*${ARG}*"
done
该脚本来自网络,非常简洁,优雅。
 
通过该脚本来学习 shell,脚本中包括如下几个 shell 知识点:
  • Shebang 行
  • 变量
  • 循环
  • 列表
  • 参数
  • 函数
  • 判断
  • set
## Shebang 行
Shebang 行是脚本的第一句,通常记为 #!/bin/bash 这种形式,指定执行该脚本需要用到的解释器。如果不加,在执行脚本的时候可通过命令 /bin/bash 指定。
 
## 变量
变量在 shell 中写作 variable=value 的形式(等号两边不能有空格!),variable 为变量名,value 为变量的值。
 
变量名需遵守以下命名规则:
  • 由字母,数字,下划线组成。
  • 变量名开头不能是数字,可以是字母或下划线。
  • 变量名中不允许出现空格和标点符号。
 
shell 将所有 value 看作字符串,如果 value 有空格,则需使用引号将 value 括起来。
 
常用的几种变量写法:
MATCH="-iname"
MATCH=-iname NAME="lian hua"
 
可通过在变量名前加美元符 $ 或加大括号 ${variable} 的形式引用变量:
echo $MATCH

echo ${MATCH}
 
注意,bash 读取不存在的变量,不会报错,会打印出空字符,如下:
[lianhuasheng@demo home]$ echo $lianhua

[lianhuasheng@demo home]$ 
 
在脚本执行的时候,如果变量不存在一般会期望脚本报错,这时候 set 命令就派上用场了。
 
## set
set 可用来设置子 shell 的运行环境,不加任何参数的 set 会 show 出当前 shell 的自带环境变量和自定义环境变量等。另一方面,set 也可用来编写更安全的 shell 脚本。
 
set -e 命令可使得在其后执行的命令,如果失败了即报错,后续的命令将不被执行。如果期望命令执行失败后,后续命令还能继续执行,可打开 set +e 选项:
set -e

command1
command2 set +e
 
set -u 可使得bash 在读取不存在变量的时候报错。
 
## 循环
在上例中使用到了 while 和 for 循环:
 
while 循环的语法格式如下:
while condition; do
commands
done
 
for 循环的语法格式有三种,分别是:
## 1. normal for script
for variable in list; do
commands
done ## demo for script
#!/bin/bash for i in lian hua sheng; do
echo $i
done ## 2. c style for script
for (( expression1; expression2; expression3 )); do
commands
done
其中,c 语言风格的 for 循环中,expression1 用来设置循环初始值,expression2 用来设置循环结束条件,expression3 用来更新值。
 
## 列表
上小节看到 for 循环中的循环体是 list 列表,列表可通过大括号扩展或者参数传递等的形式取得。
 
# 大括号扩展
使用大括号扩展 {start..end} 形式扩展值为列表:
[lianhuasheng@demo home]$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
 
将扩展出的列表运用于 for 循环中:
[lianhuasheng@demo home]$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
注意,默认 echo 输出的文本文件后加 \n 换行符,所以这里指定 echo 的 -n 选项取消换行符。
 
# 参数传递
除了大括号扩展,还有一种常见的组成列表的形式是参数传递。参数传递,即在执行脚本时指定的参数,shell 脚本中分别使用如下几种符号表明参数:
  • $0: 脚本文件名。
  • $1 - $9: 脚本的第 1 个参数到第 9 个参数,超过 9 个参数使用 ${10}, ${11}... 形式表示。
  • $#: 传入脚本的参数数量。
  • $@: 传入脚本中的全部参数,它是一个列表。
[lianhuasheng@demo home]$ cat parameter.sh
#!/bin/bash
# script.sh echo "all parameters:" $@
echo "number of parameters:" $#
echo '$0 = ' $0
echo '$1 = ' $1
echo '$2 = ' $2
echo '$3 = ' $3 [lianhuasheng@demo home]$ ./parameter.sh lian hua
all parameters: lian hua
number of parameters: 2
$0 = ./parameter.sh
$1 = lian
$2 = hua
$3 = # $3 没有读取参数,并没有报错
 
在 for 循环中常用 $@ 作为循环体:
for value in "$@"; do
echo ${value}
done
 
## 数组
for 循环中还可将数组作为循环体,在上例脚本中看到这样一条语句 ARG=("$@"),其中圆括号 () 即是将字符串转为数组的符号。
 
# 创建数组
创建数组有多种方式:直接赋值,间接赋值,外部赋值等方式:
 
1. 直接赋值:
[lianhuasheng@demo home]$ arg=(lian hua sheng)
[lianhuasheng@demo home]$ echo ${arg[@]}
lian hua sheng
 
2. 间接赋值:
[lianhuasheng@demo home]$ arg[0]=da
[lianhuasheng@demo home]$ arg[1]=shuai
[lianhuasheng@demo home]$ arg[2]=ge
[lianhuasheng@demo home]$ echo ${arg[@]}
da shuai ge
 
3. 外部赋值:
[lianhuasheng@demo home]$ read -a arg
hei hei hei
[lianhuasheng@demo home]$ echo ${arg[@]}
hei hei hei
 
外部赋值通过使用 read 命令,将用户的输入读入到数组 arg 中。
 
# 读取数组
通用的读取数组中的元素有两种方式:读取单个元素和读取所有元素:
 
1. ${arg[index]} 读取单个元素:
[lianhuasheng@demo home]$ echo ${arg[@]}
da shuai ge
[lianhuasheng@demo home]$ echo ${arg[1]}
shuai
 
2. 读取所有元素:
[lianhuasheng@demo home]$ echo ${arg[@]}
da shuai ge [lianhuasheng@demo home]$ echo ${arg[*]}
da shuai ge
 
通过 ${array[@]} 和 ${array[*]} 都可读取数组的所有元素,$array[*] 相当于不加双引号的 $array[@],加不加双引号的区别可看下例:
[lianhuasheng@demo home]$ arg=(lian "hua sheng" da "shuai-ge")

[lianhuasheng@demo home]$ for value in ${arg[*]}; do echo "parameter: " ${value}; done
parameter: lian
parameter: hua
parameter: sheng
parameter: da
parameter: shuai-ge [lianhuasheng@demo home]$ for value in "${arg[*]}"; do echo "parameter: " ${value}; done
parameter: lian hua sheng da shuai-ge [lianhuasheng@demo home]$ for value in ${arg[@]}; do echo "parameter: " ${value}; done
parameter: lian
parameter: hua
parameter: sheng
parameter: da
parameter: shuai-ge [lianhuasheng@demo home]$ for value in "${arg[@]}"; do echo "parameter: " ${value}; done
parameter: lian
parameter: hua sheng
parameter: da
parameter: shuai-ge
 
从示例中可以看出,当 $array[@] 加上双引号之后可正确输出数组 arg 中的元素,不加双引号的 $array[@] 和 $array[*] 的结果一致,加了双引号的 $array[*] 会将数组中所有元素作为单个字符串返回。
 
注意,不加索引读取数组元素读到的是第一个数组元素:
[lianhuasheng@demo home]$ echo $arg
lian
[lianhuasheng@demo home]$ echo ${arg}
lian
[lianhuasheng@demo home]$ echo $arg[0]
lian[0]
[lianhuasheng@demo home]$ echo ${arg}[0]
lian[0]
 
通过 $arg 和 ${arg} 两种方式读取数组第一个元素,通常两种方式读取变量的结果是一致的,不过推荐使用 ${ } 这种方式读取变量,它可以精确界定变量名称的范围。
如果读取变量时不用大括号,则 bash 会解析 $arg, 然后将 [0] 原样输出。
 
## 条件判断
条件判断是使用 if..elif..fi 根据指定条件判断命令执不执行的判断语句,它的语法如下:
if conditions; then
commands
elif conditions; then
commands
else
commands
fi
 
其中,elif 和 else 是可选的。
 
条件判断有多种判断表达式,如下:
  • 文件判断
  • 字符串判断
  • 整数判断
  • 正则判断
  • test 判断逻辑运算
  • 算术判断
  • 普通命令的逻辑运算
 
这里,脚本中的判断表达式皆属于字符串判断,其判断表达式为:
  • [ string ]:string 不为空,则判断为真。
  • [ string1 = string2 ]:string1 和 string2 字符串相同则判断为真,同 [ string1 == string2 ]。
  • [ string1 != string2 ]:string1 和 string2 不同则判断为真。
  • [ -n string ]:string 长度大于 0 则判断为真。
  • [ -z string ]:string 长度等于 0 则判断为真。
 
注意,这里判断表达式也使用到了 test 命令,test 有三种形式,分别是:
# 1 style of test
test expression # 2 style of test
[ expression ] # 3 style of test
[[ expression ]]
 
所以,[ -n string ] 判断表达式又可写成 test -n string 这种形式。
 
关于其它判断表达式的使用可看这里
 
## 函数
shell 中有两种函数写法:
# 1 style of function
function fn {
commands
} # 2 style of function
fn() {
commands
}
 
介绍函数主要从以下几个角度入手:函数参数,函数返回值和函数变量:
 
# 函数参数
通常执行脚本传递的参数即可作为函数的参数,但是函数也支持自定义传参:
#!/bin/bash

function input_param {
echo "I am input function, the input parameters are: "
echo "$@"
} function input_defined_param {
echo "I am input defined function, the defined parameters are: "
echo "The first parameter is: " "${1}"
echo "The second parameter is: " "${2}"
echo "The totally parameters are: " "${@}"
} input_param ${@}
input_defined_param lian hua
 
和脚本中参数类似,函数中也可使用 ${1}/${@}/$#/$* 等参数符号。但是,函数使用特殊参数环境作为自己的参数值,它无法直接获取脚本在命令行中的参数值。因此,需要传递参数给函数。
 
# 函数返回值
函数中可使用 return 返回函数执行结果,在调用函数之后可使用 $? 查看函数返回结果:
[lianhuasheng@demo home]$ ./function_return.sh
127
[lianhuasheng@demo home]$ cat function_return.sh
#!/bin/bash function_return() {
return 127
} function_return
echo $?
 
其中,$? 是 bash 提供的特殊变量,它是上一条命令的退出码,如果 $? 为 0 则表示命令执行成功,非零表示执行失败:
[lianhuasheng@demo home]$ cd lianhua
-bash: cd: lianhua: No such file or directory
[lianhuasheng@demo home]$ echo $?
1 [lianhuasheng@demo home]$ cd query/
[lianhuasheng@demo query]$ echo $?
0
 
除了 return 返回函数结果之外,在函数或者脚本中也可使用 exit 返回退出码,bash 会读取返回的退出码,并且脚本 exit 之后的语句不会被执行。
[lianhuasheng@demo home]$ cat function_exit.sh
#!/bin/bash function_exit() {
exit 127
} function_exit
echo "kissMe"
[lianhuasheng@demo home]$ ./function_exit.sh # echo "kissMe" 没有执行到
[lianhuasheng@demo home]$ echo $?
127
[lianhuasheng@demo home]$ vi function_exit.sh
[lianhuasheng@demo home]$ ./function_exit.sh
[lianhuasheng@demo home]$ echo $?
0
 
# 函数变量
函数中声明的变量都是全局变量,可使用 local 将变量转为局部变量:
[root@demo bash]# cat function_variable.sh
#!/bin/bash name="lian hua" function rename {
echo "My original name is: " "${name}"
name="${1}"
echo "Now, My name is: " "${name}"
} function naming {
initName="lao wang"
} naming
echo ${initName} # 函数外可以使用函数内定义的变量 rename "shuai ge"
echo "once again, my name is: " "${name}" # 函数内可以修改函数外定义的全局变量 [root@demo bash]# ./function_variable.sh
lao wang
My original name is: lian hua
Now, My name is: shuai ge
once again, my name is: shuai ge [root@demo bash]# cat function_variable.sh
#!/bin/bash
function naming {
firstName="wang"
local lastName="lao"
} naming
echo ${firstName} set -eux
echo ${lastName}
set +eux [root@demo bash]# ./function_variable.sh
wang
./function_variable.sh: line 12: lastName: unbound variable # lastName 是局部变量,无法引用
 
 

入门 shell 从脚本开始 - lazy_find的更多相关文章

  1. shell script 脚本编程

    介绍 Shell脚本编程30分钟入门 Shell 教程 Linux 的 Shell 种类众多,常见的有: Bourne Shell(/usr/bin/sh或/bin/sh) Bourne Again ...

  2. shell及脚本4——shell script

    一.格式 1.1 开头 必须以 "# !/bin/bash"  开头,告诉系统这是一个bash shell脚本.注意#与!中间有空格. 二.语法 2.1 数值运算 可以用decla ...

  3. 【Telnet】使用Telnet协议连接到远程Shell执行脚本

    介绍 本文介绍如何通过Telnet协议连接到远程Shell,执行脚本,并获取执行结果: 相关文章: <[Jsch]使用SSH协议连接到远程Shell执行脚本>http://www.cnbl ...

  4. shell自动计算脚本

    shell自动计算脚本 #!/bin/bash echo $(($)) [root@bogon ~]# sh b.sh 123+123246 let用户声明这个操作是要计算,后者的效率更高 (expr ...

  5. Shell菜单脚本

    今天在这儿给大家分享一个我简单编写的Shell菜单脚本,傻瓜式的人机交互,人人都可以操作linux. #!/bin/sh #Shell菜单演示 function menu () { cat <& ...

  6. shell常见脚本30例

    shell常见脚本30例 author:headsen chen  2017-10-19  10:12:12 本文原素材出自网上,特此申明.有些地方加入我自己的改动 常见的30例shell脚本 1.用 ...

  7. shell常用脚本

    shell常用脚本 author:headsen chen  2017-10-17 15:36:17 个人原创,转载请注明,否则依法追究法律责任 1,vim  name.grep.sh 2,cat   ...

  8. 一篇关于Maven项目的jar包Shell启动脚本

    使用Maven作为项目jar包依赖的管理,常常会遇到命令行启动,笔者也是哥菜鸟,在做微服务,以及服务器端开发的过程中,常常会遇到项目的启动需要使用main方法,笔者潜心的研究了很多博客,发现大多写的都 ...

  9. Linux shell编写脚本部署pxe网络装机

    Linux shell编写脚本部署pxe网络装机 人工安装配置,Linux PXE无人值守网络装机  https://www.cnblogs.com/yuzly/p/10582254.html 脚本实 ...

  10. 使用shell解析脚本依赖关系,并自动补数

    将脚本依赖关系放到表中 使用shell解析脚本依赖关系,递归的计算各个脚本. #!/bin/bash # dm 补数 basepath=$(cd ``; pwd) cd $basepath sourc ...

随机推荐

  1. 解决yolo+cudnn+opencv+gpu的一些问题

    问题描述: 在makefile文件中修改GPU=1 CUDNN=1 OPENCV=1,然后重新make,执行命令时出现: Yolov3 darknet: ./src/cuda.c:36: check_ ...

  2. 算法那么多,AI量化交易策略如何选择最佳算法?

    常见算法优劣比较 算法没有最好,只有更好. 这个问题的答案取决于许多因素,例如股票市场的条件,数据集的质量和特征工程的有效等.接下来,我们来看看这些算法的优势和劣势: 神经网络:适用于复杂的非线性问题 ...

  3. 一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器

    前言 经常看到有小伙伴在技术群里问有没有什么好用且快速的开发框架推荐的,今天就给大家分享一款基于MIT License协议开源.免费的.NET Core快速开发框架.支持多种前端UI.内置代码生成器. ...

  4. 数字孪生结合GIS能够为城市灾害预防工作提供什么帮助?

    数字孪生技术结合GIS(地理信息系统)在城市灾害预防工作中发挥着重要的作用,为城市的安全和可持续发展提供了关键帮助.数字孪生是一种将现实世界与数字虚拟世界相结合的技术,可以帮助城市规划者和管理者更好地 ...

  5. iMessage群发,iMessage群发功能,iMessage群发功能设计,iMessage群发系统

    在数字通讯时代,群发消息已经成为我们日常生活中不可或缺的一部分,无论是商务.社交还是日常沟通,群发功能都大大提高了消息传递的效率和便利性. 而在众多的通讯软件中,iMessage无疑是其中的佼佼者,今 ...

  6. ElasticSearch之Slow Log

    ElasticSearch的慢日志,相关的参数及配置方法. 在log4j2.properties中配置慢日志的输出文件名. Search Slow Log 相关参数 index.search.slow ...

  7. TypeScript核心基础

    前言 为了方便我们直接使用脚手架让他帮我们直接编译就完事了 创建一个 Vue 应用 前提条件 熟悉命令行 已安装 16.0 或更高版本的 Node.js npm init vue@latest 这一指 ...

  8. 文心一言 VS 讯飞星火 VS chatgpt (40)-- 算法导论5.4 4题

    四.一次聚会需要邀请多少人,才能让其中 3 人的生日很可能相同? 文心一言: 为了解决这个问题,我们需要先计算出所有可能的生日组合数,然后计算出其中生日相同的组合数. 已知需要邀请的人数为:23人 根 ...

  9. Redis核心技术与实战

    最近在读一篇关于Redis的专栏,叫做<Redis核心技术与实战>,作者在Redis方面研究颇深,读后非常受益,特在此做记录. 一.Redis基础 1)知识图和问题画像图 Redis知识全 ...

  10. MySQL进阶篇:详解MySQL存储引擎选择

    MySQL进阶篇:第一章_一.五_MySQL存储引擎选择 在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎.对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组合. InnoDB: ...