赞
踩
shell/bash其实就是我们日常在unix系统终端中执行的语句,只是通常我们在命令行中都是单行语句执行的,而有时,我们希望将一些操作命令写到一个文本中,让电脑自动按顺序或是并行地执行这些命令,这样我们就不需要时刻守在电脑前一行行去执行命令了。
shell文件通常以.sh
为后缀,如test.sh
,其实质是一个文本文件。
通常,文件的第一行是该文件所需要使用的解析器的定义,一般使用bash,命令如下:
#!/bin/bash
比如要运行名为test.sh
的脚本文件,首先我们先将命令行路径进入到该脚本文件所在路径下,有三种形式(任选其一即可):
./test.sh # 先按照文件中#!指定的解析器解析
bash test.sh # 先用bash解析器解析
. test.sh # 直接使用默认解析器解析
在运行的时候,可能你会遇到如下报错:
-bash: ./test.sh: Permission denied
说明test.sh
文件还没有执行权限,我们通过命令行给它加上执行权限:
chmod +x test.sh
之后再运行test.sh
文件就可以了。
单行注释与python语言的一致,由单个#
开始。
语法格式:
echo hello world
上面都没有给出运行示例,现在,让我们打开新建的test.sh文件,在里面输入如下内容:
然后打开命令行,执行文件,就可以看到输出了:
shell里的变量不需要指明变量类型,类似于python,可以直接进行声明和赋值。比如:
myage=18 # 声明一个变量myage,值为20
但是,需要注意如下两点:
myage=18
和myage=“18”
在使用的时候都是一样的变量的使用方式有两种:
$变量名
${变量名}
这两种方式都是可以的,第2种方式在变量名前后加上{},主要是可以界定变量名的范围。比如使用上面定义的变量:
echo I am ${myage}years old
# 输出为I am 18years old
但是如果没有使用花括号:
echo I am $myageyears old
# 输出为I am old
(( ))
是一种扩展运算符,只要符合C语言标准的语句都可以在这里面执行。比如使用上面定义的myage变量,现在我要让它自增1。如果直接写:
myage+=1
# 输出myage,会发现结果是181,也就是被当成字符串运算了
而要获得正确结果,应该写成:
((myage++))
((myage+=1))
# 以上两种写法都可以,结果均为19
需要注意的一点是,shell只能作整数运算,对于浮点数都是直接当作字符串处理的。
此外,除了(( ))
之外,shell中还有( )
、[ ]
、[[ ]]
等等括号,用法不尽相同,可以参考:shell中各种括号的作用()、(())、[]、[[]]、{}
要将多个不同的语句放在同一行,需要在语句末加上;
进行分隔。比如:
myage=18; echo I am ${myage}years old
如果一个语句太长了影响阅读,可以通过\
将一行语句写为多行。比如:
python test.py --config config.txt \
--input data.txt \
--output output.txt
这是一个运行python文件的命令,这里将其分为三行。注意这里续行符的左边都有一个空格,这样的话这三行命令就等同于如下一行命令了:
python test.py --config config.txt --input data.txt --output output.txt
也即不同参数之间存在一个空格。如果没有了续行符左侧的空格,就会等同于:
python test.py --config config.txt--input data.txt--output output.txt
这里,续行符左侧的每个空格和实际空格是一一对应的,如果有两个空格,那将命令放在一行的时候也是两个空格。但是续行符右侧的空格数量和换行之后命令前的空格数量都是不影响命令的,比如:
python test.py --config config.txt \
--input data.txt \
--output output.txt
这样写命令也是可以的。
for循环的一般格式为:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
如果要将其写成一行,则是:
for var in item1 item2 ... itemN; do command1; command2… done;
比如:
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
输出结果为:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
除了这种方式外,类似于C语言的for循环也是可以的,比如:
for((i=1;i<=5;i++))
do
{
echo $i
}
done
输出的结果为:
1
2
3
4
5
需要注意的是,这里for循环需要两个小括号(扩展C语言计算),不能将其中一个去掉,否则会报语法错误。
一般格式为:
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
其中最后的fi
是if
语句结束的标记,elif
、else
都是可选的。
一个例子:
a=10
b=20
if (( $a == $b ))
then
echo "a 等于 b"
elif (( $a > $b ))
then
echo "a 大于 b"
elif (( $a < $b ))
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
输出为:
a 小于 b
shell脚本默认是串行执行命令的,也就是只有当上一行语句运行完成后才会运行下一行命令。但是有时候,我们希望命令是一起执行的。比如,我的服务器上有多张GPU,想在每张GPU上都跑不同的任务,它们之间互不相干,因此可以同步执行。并行执行的方法也很简单,就是直接在上一行命令的末尾加上&
符号即可。比如:
python test1.py&
python test2.py&
python test3.py
如果使用for循环,也可以简单地写为:
for((i=1;i<=3;i++))
do
{
python test${i}.py
};
done
使用&运算符可以使命令同步执行,但是有时,下一步的程序是需要依靠上一步的执行结果来作为输入的。那么,我们需要确保上一步完全执行完毕了,才运行下一步的命令。这时,我们可以使用wait
关键字。比如:
python test1.py
wait
python test2.py
这样,就只能在test1完成后,才会执行test2任务了。
sleep命令可以使命令行暂停一定时间再执行。比如:
python test1.py
sleep 10
python test2.py
这样,test1执行完之后,会等待10s,之后才执行test2。
shell/bash命令还有丰富的语法内容,这里只列出一些基本的命令,可以供日常简单的使用。如果还需要更复杂高级的应用,可以寻找专业的资料进一步学习。
根据上述内容,我写出了如下脚本文件,该文件用于运行mega-nerf网络中。
#!/bin/bash ##################################################### variables ######################################################## # experiment id expid=14 # colmap sparse model path, where contain cameras,images,points3D modelpath=../../data166/ISPRS1/ISPRS1/rescale_2/sparse # input scene images path imagespath=../../data166/ISPRS1/ISPRS1/rescale_2/images # image number for validation numval=24 # PCA rotation if coordinate is not aligned pcarotate=--pca_rotate # output meganerf files path megapath=../../outdata/isprs/experiment${expid}/isprs_mega # where contain rayrange message, can be generate automatically configfile=../../outdata/isprs/experiment${expid}/rayrange.yaml # mask path maskpath=../../outdata/isprs/experiment${expid}/mask16 # grid dim griddim1=4 griddim2=4 # scale to downsample images trainscalefactor=2 # experiment prefix(where to store training results) expprefix=../../outdata/isprs/experiment${expid}/exp # chunk prefix(where to store chunk message) chunkprefix=../../outdata/isprs/experiment${expid}/chunk # where to save log files(with prefix) logdir=../../outdata/isprs/experiment${expid}/chunks # depth guide path depthmappath=../../outdata/depth # checkpoint prefix(where store the network parameters) ckptprefix=../../outdata/isprs/experiment${expid}/exp- # centroid path centroidpath=${maskpath}/params.pt # to merge the models with how many training iterations trainiterations=50000 # file path to store merged model mergedpath=../../outdata/isprs/experiment${expid}/merged${trainiterations}.pt # path to store evaluation results evalpath=../../outdata/isprs/experiment${expid}/eval # valuation scale valscalefactor=8 ##################################################### commands ######################################################### # colmap to meganerf python scripts/colmap_to_mega_nerf.py \ --model_path ${modelpath} \ --images_path ${imagespath} \ --num_val ${numval} \ --output_path ${megapath} \ --config ${configfile} \ ${pcarotate} wait # generate clusters python scripts/create_cluster_masks.py \ --config ${configfile} \ --dataset_path ${megapath} \ --output ${maskpath} \ --grid_dim ${griddim1} ${griddim2} wait # training: run_4 for ((i=0;i<4;i++)) do { CONFIG_FILE=${configfile} \ DATASET_PATH=${megapath} \ MASK_PATH=${maskpath} \ TRAIN_SCALE_FACTOR=${trainscalefactor} \ EXP_PREFIX=${expprefix} \ CHUNK_PREFIX=${chunkprefix} \ DEPTHMAP_PATH=${depthmappath} \ nohup python -m parscript.dispatcher parscripts/run_4_${i}.txt -g 8 > ${logdir}${i}.log 2>&1 & }& done wait # merge models python scripts/merge_submodules.py \ --config_file ${configfile} \ --ckpt_prefix ${ckptprefix} \ --centroid_path ${centroidpath} \ --train_iterations ${trainiterations} \ --output ${mergedpath} wait # evaluate model python mega_nerf/eval.py \ --config_file ${configfile} \ --exp_name ${evalpath} \ --dataset_path ${megapath} \ --container_path ${mergedpath} \ --val_scale_factor ${valscalefactor}
部分内容参考:
shell脚本的使用入门(超全)
Shell 流程控制
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。