一、背景

最近在写一个私有化部署脚本的时候频繁的使用了ls和grep的组合,但是插件ShellCheck却一直在给我标黄,我这该死的洁癖终于在今天受不了了,这个使用了这么多年的好搭档怎么就那么不讨喜呢!





二、ShellCheck的规范

很明显,提示告诉我们不要使用ls|grep的搭配,建议我们使用一个通配符或者带有条件的循环。。。

一个ls都有这么多讲究,我们来看个wiki的使用反例:

$ touch 'a space' $'a\nnewline'
$ echo "don't taze me, bro" > a
$ ls | cat
a
a
newline
a space

ls后面用管道符输出的结果怎么和预想的不一样??,我们来看看文件列表:

$ ls -l
total 8
-rw-r----- 1 lhunath lhunath 19 Mar 27 10:47 a
-rw-r----- 1 lhunath lhunath 0 Mar 27 10:47 a?newline
-rw-r----- 1 lhunath lhunath 0 Mar 27 10:47 a space

Linux中的文件名是个神奇的存在,你可以使用几乎任意字符:空格、换行符、逗号、管道符等等。

默认模式下,如果输出不是终端的话,ls会用换行符分割开文件名,所以问题就来了:从ls的输出中,您或计算机都无法知道它的哪些部分构成了文件名。是每个字吗?不。是每行吗?不。这个问题没有正确答案,只有:你不知道。

哈哈哈,惊不惊喜?意不意外?当然,平时的使用其实都没有问题的,只是插件不建议我们这么用,那我就是改改我的使用吧,洁癖太可怕了。。。

三、修改写法

1、ls | grep file

这个其实挺好改的,我的本意是想看下prometheus的目录权限、grafana目录下grafana.db文件的权限

查一个目录的权限可以修改为(d指定只看目录):

➜  service-monitor git:(master) ✗ ls -dl prometheus
drwxr-xr-x 17 Charles staff 544 8 26 21:09 prometheus

由于ls本身就有检索的功能,查看文件的权限就很简单了

➜  service-monitor git:(master) ✗ ls -l grafana/grafana.db
-rw-rw-rw- 1 Charles staff 2232320 8 26 22:36 grafana/grafana.db

2、ls | grep regexp

简化一下原有语句:

for tarfile in $(ls images | grep '.tar$'); do echo "loading $tarfile"; done

本意是想加载images文件夹下所有tar文件,先打印,后load镜像。

我们知道ls后面的查询只能跟通配符,不能跟正则表达式,所以更改如下:

➜  build git:(master) ✗ ls images | grep '.tar$'
monitor.tar
➜ build git:(master) ✗ ls images/*.tar
images/monitor.tar

然后for循环可修改为:

➜  build git:(master) ✗ file=$(ls images | grep '.tar$')
➜ build git:(master) ✗ echo $file
monitor.tar
➜ build git:(master) ✗ file=images/*.tar
➜ build git:(master) ✗ echo $file
images/*.tar
➜ build git:(master) ✗ for tarfile in images/*tar; do echo "loading $tarfile"; done
loading images/monitor.tar

3、ls | grep -v multi

这个语句的本意是查询出当前目录下所有不是.sql或.zip结尾的文件

由于ls不能用正则,也不能用反选,这个语句的修改一开始让我还很头疼,后来发现有个shell操作选项shopt,这个工具可以激活或关闭指定的shell行为选项。

比如我现在要打开extglob模式,该模式可以给ls扩展匹配操作符,能使文件匹配更加方便. 不然不识别!

开启命令:

shopt -s extglob

关闭命令:

shopt -u extglob

5个模式匹配操作符

  • ?(pattern-list) - 所给模式匹配0次或1次;
  • *(pattern-list) - 所给模式匹配0次以上包括0次;
  • +(pattern-list) - 所给模式匹配1次以上包括1次;
  • @(pattern-list) - 所给模式仅仅匹配1次;
  • !(pattern-list) - 不匹配括号内的所给模式。
#反选删除文件:
#(打开extglob模式)
shopt -s extglob
rm -fr !(file1) #多个要排除的:
rm -rf !(file1|file2)

所以这时候我们的修改就很简单了

shopt -s extglob
rm -rf !(*.zip|*.sql) && ls -l

四、最后

改完之后心情豁然开朗,很多时候规范不只是有束缚编码行为的好处,还可以使你对代码使用有着更深的理解。

五、参考

ShellCheck Wiki: Don't use ls | grep

ShellCheck Wiki: Iterating over ls output is fragile. Use globs.

Why you shouldn't parse the output of ls

Pattern Matching In Bash

shopt

linux extglob模式 和rm反选

Shell编程规范:Don't use ls | grep的更多相关文章

  1. 01 shell编程规范与变量

    前言: 大家对shell脚本应该都不算陌生了,如果突然问你什么是shell脚本?是干什么用的?由什么组成以及怎么使用?变量的概念是什么?作用范围是什么?变量间的算术运算怎么表示?你能很容易答出来吗 本 ...

  2. SHELL编程规范与变量

    shell相比标准开发语言比如JAVA,C,C++来说还是比较简单的,其实就是一堆命令的集合而已,初学者从简单的shell脚本学起,至于shell编程还是要有编程思想在里面,因此,循序渐进很重要,先研 ...

  3. shell编程规范:引用

    Shell代码规范 作 者: 毕小朋 用 途: 规范Shell代码书写,方便查看与修改 博 客: http://blog.csdn.net/wirelessqa 参 考: http://www.ohl ...

  4. shell 编程四剑客简介 find sed grep awk(微信公众号摘抄)

    一,Shell编程四剑客之Find 通过如上基础语法的学习,读者对Shell编程有了更近一步的理解,Shell编程不再是简单命令的堆积,而是演变成了各种特殊的语句.各种语法.编程工具.各种命令的集合. ...

  5. Python subprocess shell 编程规范

    使用subprocess通过shell调用另一个模块组件时,需要对返回的code进行判断.判断结果为执行失败时需要raise Exception,不然调用树过于复杂时,我们很难跟踪到异常发生的位置.s ...

  6. shell编程规范

    1 脚本名以.sh结尾,名称尽量见名之意,比如ClearLog.sh Clear_Log.sh clearlog.sh SerRestart.sh Ser_Restart.sh;2 尽量使用UTF-8 ...

  7. Shell脚本之编程规范和变量

    Shell脚本编程规划和变量 1.Shell脚本概述 2.Shell编程规划 3.重定向与管道 4.Shell脚本变量 1.Shell脚本概述 Shell的作用:充当"翻译官"的角 ...

  8. shell编程企业级实战

    如何才能学好Shell编程 为什么要学习shell编程 Shell是Linux底层核心 Linux运维工作常用工具 自动化运维必备基础课程 学好shell编程所需Linux基础 熟练使用vim编辑器 ...

  9. Shell编程-01-Shell脚本初步入门

    目录 什么是Shell 什么是Shell脚本 Shell脚本语言的种类 常用操作系统默认Shell Shell 脚本的建立和执行 脚本规范 什么是Shell     简单来说Shell其实就是一个命令 ...

随机推荐

  1. 论文解读《Plug-and-Play Priors for Model Based Reconstruction》

    这篇论文主要概述了model-baesd的方法在解决图像恢复的逆问题的很好的效果,降噪问题其实就是前向模型的H是一个恒等算子,将state-of-the-art的降噪算法(先验模型)和相对应的逆问题的 ...

  2. 技术选型:为什么批处理我们却选择了Flink

    最近接手了一个改造多平台日志服务的需求,经过梳理,我认为之前服务在设计上存在缺陷.经过一段时间的技术方案调研,最终我们决定选择使用 Flink 重构该服务. 目前重构后的服务已成功经受了国庆节流量洪峰 ...

  3. Jenkins配置,tomacat版本输出乱码和页面打开报404的问题

    1.打开tomact下的startup.bat,tomcat版本控制台中文输出乱码,解决方法是去tomacat安装路径下的conf目录,打开logging.properties文件,将java.uti ...

  4. Java中的微信支付(2):API V3 微信平台证书的获取与刷新

    1. 前言 在Java中的微信支付(1):API V3版本签名详解一文中胖哥讲解了微信支付V3版本API的签名,当我方(你自己的服务器)请求微信支付服务器时需要根据我方的API证书对参数进行加签,微信 ...

  5. linux下生成动态库和链接动态库

    1.生成动态库 src/test.h #ifndef _TEST_H_HH #define _TEST_H_HH void print(); #endif src/test.cpp #include ...

  6. Luogu P3262 [JLOI2015]战争调度

    题意 给定一棵高度为 \(n\) 的完全二叉树,可以将节点设置成两种状态.如果某个叶子 \(x\) 的状态为 \(i\) 同时他的某个祖先也为 \(i\),那么这个叶子就会对祖先产生 \(f_{x,i ...

  7. Java学习的第二十一天

    1.综合实例 error异常:error指的是错误,通常是程序员不可能通过代码来解决的问题,底层环境或硬件问题,也就是说在程序中用户不用捕获error及任何error子类的异常. exception指 ...

  8. Java基础知识(三)

    一.hashCode 与 equals (重要) 面试官可能会问你:"你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?" 1 ...

  9. .net 实现签名验签

    本人被要求实现.net的签名验签,还是个.net菜鸡,来分享下采坑过程 依然,签名验签使用的证书格式依然是pem,有关使用openssl将.p12和der转pem的命令请转到php实现签名验签 .ne ...

  10. day85:luffy:购物车根据有效期不同切换价格&购物车删除操作&价格结算&订单页面前戏

    目录 1.购物车有效期切换 2.根据有效期不同切换价格 3.购物车删除操作 4.价格结算 5.订单页面-初始化 1.购物车有效期切换 1.关于有效期表结构的设计 1.course/models.py ...