bash命令
一、Bash相关
1、运行Bash
(1)可以直接在命令行中运行,例如
cd \xxx
(2)存储在脚本文件中执行,扩展名为.sh或者没有扩展名。
如果是用脚本文件运行:第一行写上#!/bin/bash;其中#!也叫做Shebang,另外还需要把该.sh文件设置为可执行文件。
chmod +x
在计算领域中,Shebang是一个由井号和叹号构成的字符序列#!,其出现在文本文件的第一行的前两个字符。 在文件中存在Shebang的情况下,类Unix操作系统的程序加载器会分析Shebang后的内容,将这些内容作为解释器指令,并调用该指令,并将载有Shebang的文件路径作为该解释器的参数。
(3)bash脚本开头经常会有set -x参数,表示当有语句执行错误时,整个脚本能够停下来,而set -x命令表示在调试Bash脚本时,希望能够被执行的具体命令,而不仅仅是输出,因此常用
set -xe
(4)bash命令行Terminal撤销输入 Ctrl+Shift±
2、变量
<variable>="value"
例如:
des="sd"
注意=两边不能有空格!!
读取变量使用${variable}
例如:
echo ${des}
如果读取的变量后面不是分隔符(回车),那么必须使用{}
例如:
cp $filename ${des}_backup
否则系统会任务des_backup是一个变量
Bash中的单引号和双引号都表示字符串,但是双引号中的变量会展开,单引号不会。
例如:
s1='sds'echo${s1}s2="333"echo"${s2}dfdf"echo'${s2}dfdf'
返回
sds
333dfdf
${s2}dfdf
双引号中使用$会将$按照原字符串输出。
3、内置变量
系统一些内置变量,例如$PATH 表示搜索可执行文件的路径列表
4、环境变量
运行
python train.py
时会给进程设置环境变量CUDA_VISIBLE_DEVICES。
此时
python train.py
只能看到0,1两块GPU,不能使用其他的GPU。
普通变量的赋值和export有什么区别?
直接在Shell中赋值的变量,子进程不可见,而用export赋值的变量,子进程可见。
或者在同一行先写变量赋值,在执行子进程,例如:
some_var=kk python -c 'import os; import sys;print os.environ.get(sys.argv[1])' some_var
,这样子进程是可见的,而在下一个命令中是没有该变量的。
exportsome_var='kk'
python -c'import os; import sys;print os.environ.get(sys.argv[1])' some_var # 这样整个本Shell周期内都是可见的。
5、source
source ./vars.sh
source后的脚本不再是新开的子shell运行,source使得vars.sh中的每一行,都像是在父Shell中执行一样。
6、输出赋值
可以用
(
c
o
m
m
a
n
d
)
把某个命令的输出赋值给某个变量例如:
‘
v
a
r
1
=
(command)把某个命令的输出赋值给某个变量 例如:`var1=
(command)把某个命令的输出赋值给某个变量例如:‘var1=(echo “sdsdsd”)`
7、运算let expr 双括号
let "a = 5+19"
echo a
返回24
let "b = 13*14"
expr会把表达式的结果输出,比如:
expr 5 * 19
!!!注意必须有空格才能当作表达式,否则就跟字符串一样的。
foo=$(expr 5 + 8)
!! 注意*号貌似会返回当前目录的所有文件和文件夹,+号是可以的,但是需要有空格。
双括号。
8、if判断语句
if<condition>then<cmd>else<cmd>fi
else语句可以省略。
例如:
if[${temp}-ge30]# -ge的意思是大于等于greate or equ。注意-ge前面只能有一个表达式,不能${a} + ${b} -ge 3thenecho"sadsad"fi
【注意这里的if内部语句前后必须有空格。】
if[-e /bin/ls ]# 判断文件是否存在thenecho"oko"fi
还有很多其他的计算表达式
上述表达式可以使用单独的命令test来判断
test5-ge4# echo$?# $?是上一个语句的返回结果,是上一个语句!如果上一个语句报错了,那么返回值会被更新成错误的
test 5 -ge 2 && echo "Condition is true" || echo "Condition is false"
,test命令常用于条件测试,其结果不会被直接输出,需要用逻辑判断来检查返回值
如果有多重判断,中间需要使用elif而不是else!!!,Bash的if语句可以嵌套
if判断是否存在某个文件夹
if [ ! -d "$output_folder" ]
如果不存在该文件夹
9、布尔运算
运算表达式可以用布尔运算连接起来,比如&&或||
if [ $code_review = "pass" ] && [ $regression_test = "pass" ]
注意多个表达式需要多个[]之间用布尔运算,而不是一个[]
10、for循环语句 for do done,while循环语句
forxin123445doecho${x}# 不要忘了$done
对于数字1-n的循环,Bash有一个内置的写法{1…n}
foriin{1...3}doecho$idone
也有类似C语言中for循环的写法:
for((i=1; i<3; i++))doecho$idone
注意可以遍历一个字符串,以空格分隔每个字符串,这个很重要
checkpoint_path="checkpoints"checkpoint_name="aaa bbb ccc ddd eee fff"datasets_name="COCO"forckptin${checkpoint_name};doecho-ne"${ckpt}:\t">>${log_name}# 追加而不覆盖fordatasetin${datasets_name};dobash /mnt/abs.sh "/mnt/${dataset}/cost.result">>${log_name}doneecho"">>${log_name}done
while循环语句
while read jpg_file; do
读取每一行的路径,并赋值给jpg_file变量
11、until语句 until do done
until[!-e"foo${suffix}"]# 直到不存在该文件名dolet suffix++
done
12、break、continue
在循环过程中可以中途退出,或者立刻运行下一次循环。
13、函数
必须在调用前定义函数
function_name(){# 注意这里的函数名后面一定要有()<command>}# 或者functionfunction_name{<commands>}
在函数里,可以用return返回结果。Shell函数的返回值只能是介于0-255之间的整数。
find_cpp_files(){localfolder="/home/tieshuai.song/"localret=$(find ${folder}-name"*.stdout"|wc-l)echo$retreturn$ret}
find_cpp_files # 这里的调用函数不需要有()echo$?# 返回上一步的计算结果
14、scope全局变量
var_change(){localvar1='local 1'echo"Inside function : var1=\"$var1\" var2=\"$var2\""var1='changed again'var2='2 changed again'}
15、调试技巧set
注意:实际调试可以用bash -x或者bash -e的方式运行脚本, 来达到set -x或者set -e的效果。 这样的好处是不需要改脚本。
程序开头设置如下,能够在碰到异常情况时停止执行。
set-x# 用于启用脚本的调试模型,会使得脚本执行时将每个要执行的命令显示出来set-e# 命令执行不成功(返回值非0)会中断,停止运行set-u# 使用未定义的变量中断set-o pipefail # 一个管道复合命令,只要有其中一个fail,整个命令就算fail
16、Bash随机数相关
使用
$RANDOM
变量以及取余运算符%来限制范围
random_number=$((1 + $RANDOM % 100))
这里如果直接用random_number=RANDOM % 100,bash会将其解释为字符串赋值,而不是取余操作,正确的操作是执行
$((...))
来进行算术运算。
17、Bash算术运算
Bash脚本中使用
$((...))
来进行算术运算,使用
-eq
来表示等于
例如下面打印1-100以内的素数
#!/bin/bashisPrime=1for((i=2; i<=100; i++))do# if Prime?for((j=2; j*j<=i; j++))doif[$((i % j))-eq0];then# isPrimeisPrime=0break;fidoneif[$isPrime-eq0];thenisPrime=1continueelseecho$ifidone
二、Bash基础知识
1、echo:
echo "dsd"
把参数输出到屏幕,并且有回车,这点跟
printf
不一样,
printf "sd"
输出最后没有回车
也就是
echo
默认会输出一个new line,而
printf
不会
echo sdsd
也可
echo -e
中-e选项是用来激活echo命令的转义字符(以\开头的例如\n换行)功能,这个很重要
echo 1111 >> a_file
将1111写入文件a_file中,如果不存在就创建这个文件
echo
默认是带回车的,如果不希望有回车,使用
echo -n abccd
类似的-n命令
2、printf
printf "sdsd
" 最后没有回车
printf sdssd
也是
printf
和C语言中的
printf
类似,格式化输出
printf "i and you %d\n" 33
3、stdout和stderr
stdout
和
stderr
: 程序的输出包括
stdout
和stderr,默认都会输出到终端屏幕上
echo “sds” > /tmp/ls.stdout可以把stdout输出到文件里面,内容为sds # 单个>
ls > /tmp/ls.stdout把ls返回的内容输出到终端上
ls1> /tmp/ls.stdout 2> /tmp/ls.stderr # stdout输出到ls.stdout,stderr输出搭配ls.stderrls&> /tmp/ls.stdall # 都保存到同一文件## rev把输入颠倒输出
```bash
rev# 先输入rev然后回车,输入👇revecho"sdssdsdddddd"# 按回车后返回"ddddddsdssds" ohce ver# 但是此时程序并没有结束,人工按Ctrl+D结束输入,再按一次会退出命令行
4、| && || bash组合命令
|
echo yitutech | rev
会把多个命令组合起来,前一个命令的输出会变成后一个命令的输入,返回hcetutiy,一定要和||区分开
&&
程序依次执行命令,如果前一个命令报错(返回值不为0)则不执行后续的命令,
echo "sds" && ls
||
前一个命令不成功,则后一个才会执行
$() 命令嵌入,可以把某一命令的输出赋给某一变量
把某个命令的输出嵌入到另一个命令中,例如
echo $(seq 1 3)
返回 1 2 3。【】seq 1 3是产生1-3的序列
checkpoint_name=$(find ${checkpoint_path}-type f -name"*embed*"|grep-oP'([^\/]*)\.[^\/]*$'|sed's/\..*//'|sort|xargs)
() 把多个命令的输出统一到某文件
当()内部多个命令,可以统一管理这些命令的输出
(echo sdsd ; ls; echo "ecccccc") > output.txt
不同命令之间用;分隔
5、Bash获取命令行参数
$1, $2, $3分别表示第一个,第二个,第三个…命令行参数,$0为bash命令本身
echo "first is $1"
获取所有的命令行参数:
"$@"
echo "$@"
获取命令行参数的个数:
"$#"
echo “$#”
版权归原作者 song43999 所有, 如有侵权,请联系我们删除。