今天下午把打包好的镜像文件上传到公司服务器上,想在服务器上导入镜像,玩了会shell挺有意思的,把其中遇到的知识点以及问题列出来总结下。
问题引出
因为上传的镜像tar包很多,一个个使用docker load -i 显得很蠢,就想玩玩shell,在网上查了一下使用shell获取文件名的方法:
cur_dir="./"
for file_name in `ls ${cur_dir}`
do
if [ "${file_name##*.}"x = "tar"x ]; then
tmp_file=`basename ${file_name}`
docker load -i ${tmp_file}
fi
done
上面代码把知识点给到大家:
- for循环结构
这个还好理解,可以把他当成python代码,for里面的do done 相当于for的代码体 `` 意思是漂里面是可执行命令,等同于$() ${} 这个意思是使用shell中的变量,如果只是变量读取可以省略这个{} 直接$ 。- if使用结构:if [ state ] ; then fi
这里注意一下:两个中括号中间必须有空格,包括if和中括号之间也要有!else结构:if [ state ]; then xxx elif [ state ] then xxx else fi - 中括号中间的state如果需要判等使用
= 单等号。 - shell的单引号和双引号是有区别的!单引号不会解析其中的表达式,就如这个
"${file_name##*.}" 这里如果使用单等号那么代表的就是纯纯的字符串。 "${file_name##*.}"x = "tar"x 这个x没有特殊含义,仅是为了避免出现前面的字符串为空的情况下会报错,可以替换成任意字符。"${file_name##*.}"x = "tar"x 中的 ## 是字符串截取, . 是截取方式,在我的代码中表示截取后缀, * 是舍弃位置,在截取方式前面表示舍弃. 前面的字符串。有这几种类似符号: – # 标记位为从前到后第一个匹配的位置 – ## 标记位为从前到后最后一个匹配的位置 – % 标记位为从后到前第一个匹配的位置 – %% 标记位为从后到前最后一个匹配的位置
优化
load成功之后,留下了一堆的tar包,为了给用户更好的体验给到一个交互shell:询问用户是否删除tar包
cur_dir="./"
for file_name in `ls ${cur_dir}`
do
if [ "${file_name##*.}"x = "tar"x ]; then
tmp_file=`basename ${file_name}`
docker load -i ${tmp_file}
fi
done
echo "remove tars?(y/n)"
read input
if [ $input = "y" ]; then
for file_name in `ls ${cur_dir}`
do
if [ "${file_name##*.}"x = "tar"x ]; then
tmp_file=`basename ${file_name}`
rm -f ${file_name}
fi
done
echo "success"
fi
知识点?来了:
- read读取shell输入字符串,并且存入input中
聪明的人应该可以看出代码有很大的重复程度,而且时间复杂度很高,这段判断文件后缀是否为tar的时间复杂度为O(2 * n * m),n是文件数量,m是文件名长度。
害怎么这么蠢呢 突然想到ls 可以加个管道呀
优化:使用变量名存储后缀,这样不用多次修改后缀,便于测试用。
cur_dir="./"
suffix="txt"
for file_name in `ls ${cur_dir} | grep "${suffix}"`
do
tmp_file=`basename ${file_name}`
echo $tmp_file
done
echo "remove tars?(y/n)"
read input
if [ $input = "y" ]; then
for file_name in `ls ${cur_dir} | grep "$suffix"`
do
echo $file_name
done
echo "success"
fi
搞定!好家伙,这个东西我竟然玩了两个小时,把正事都给忘了QwQ… 我还写了份用数组存储文件名的shell后来被覆盖不见了… 等有时间补上,或者大佬们在评论区里实现一下。
|