前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >常用简单命令_bash笔记2

常用简单命令_bash笔记2

作者头像
ayqy贾杰
发布2023-03-15 18:45:18
4950
发布2023-03-15 18:45:18
举报
文章被收录于专栏:黯羽轻扬黯羽轻扬

感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学(WebGL)、语文(课外书读后感)、英语(文档翻译) 如果觉得弱水三千,一瓢太少,可以去 http://blog.ayqy.net 看个痛快

cat(concatenate)

读取、显示、拼接文件内容

把来自标准输入的内容和文件内容拼接起来:

代码语言:javascript
复制
echo 'from stdin' | cat - test.sh

cat命令用-表示标准输入

If file is a single dash (`-‘) or absent, cat reads from the standard input.

其它常用功能选项:

代码语言:javascript
复制
# 给文件内容添上行号
cat -n test.sh
# 把文件中的连续多个空行压缩成一个
cat -s test.sh

find

基本规则

从文件目录向下遍历,匹配符合条件的,处理

代码语言:javascript
复制
# 列出当前目录下所有文件/文件夹、子文件/文件夹
find .
# 用\0分隔(文件路径里有换行符时有用)
find . -print0# 通配符
find -name "*.js"
# 忽略大小写
find -iname "*.js"
# 多条件
find . \( -name "e*" -o -name "s*" \)
# 路径匹配
find ../tnode -path "*node*"
# 与-path一样,只是参数为正则表达式
find . -regex ".*/e.*h$"
# 忽略大小写
find . -iregex ".*/e.*h$"# 否定参数(独立参数,可以配合-name/path/regex等用)
find . ! -iregex ".*/e.*h$"
# 例如排除路径含有node_modules的
find ../tnode ! -regex ".*node_modules.*"# 指定目录深度,-maxdepth 1表示向下找1级(也就是..的孩子,不找孙子)
find .. -name "*.js" -maxdepth 1
# 也可以指定起始深度,-mindepth 2 -maxdepth 2表示只在..的孙子中找,不找儿子也不找孙子的儿子
find .. -name "*.js" -mindepth 2 -maxdepth 2
# 单独用-mindepth找超过指定深度的文件(找深路径lib)
find .. -regex ".*node_modules*.*.js$" -mindepth 20

按文件类型搜索

代码语言:javascript
复制
# 指定文件/文件夹,-type f表示只输出文件
find ../tnode ! -regex ".*node_modules.*" -type f

P.S.参数顺序会影响搜索效率,比如先检查深度再过滤类型更快

文件类型与type参数值对应关系:

代码语言:javascript
复制
普通文件:f
符号链:l
目录:d
面向字符的设备文件:c
面向块的设备文件:b
套接字:s
FIFO:p

按时间搜索

每个文件有3种时间戳:

代码语言:javascript
复制
访问时间:-atime
修改时间:-mtime
变化时间:-ctime

参数值为整数,表示天数,可以前缀+-,分别表示大于,小于,例如:

代码语言:javascript
复制
# 找出父级目录中,昨天到现在访问过的文件
find .. -type f -atime -1

也有以分钟为单位的:

代码语言:javascript
复制
# -amin, -mmin, -cmin
find .. -type f -amin $((-1 * 60 * 24))

还可以指定一个文件作为参照,找出更新的(修改时间更近的)文件:

代码语言:javascript
复制
# 找出父级目录中,比~/.bash_profile更新的文件
find .. -type f -newer ~/.bash_profile

按文件大小搜索

代码语言:javascript
复制
# 当前目录下大于1K的文件
find . -type f -size +1k

支持b块, c字节, w字, k, M, G单位,注意前面小写,后两个大写,在其它命令里一般也是这样,例如split

其它用法

代码语言:javascript
复制
# 查找并删除
find . -type f -name "*.tmp" -delete
# 匹配文件权限
find . -type f -perm 777 -print
find . -type f -user ayqy

-exec结合执行其它命令

代码语言:javascript
复制
# 查找并格式化输出
find . -type f -exec printf "file: %s\n" {} \;
# 查找并备份
find . -type f -mtime +7 -exec cp {} bak/ \;

P.S.末尾转义分号用来表示-exec参数值结束,必须要有

-exec只能执行一条命令,需要执行多条的话,把命令写入文件再执行,例如把备份命令写入bak.sh

代码语言:javascript
复制
#!/bin/bash
BAK_DIR=bakif ! test -e "$BAK_DIR";
then
   mkdir "$BAK_DIR"
fifor file in "$@";
do
   cp $file "$BAK_DIR"
done

再查找执行:

代码语言:javascript
复制
find . -type f -mtime +7 -exec ./bak.sh {} \;

-prune排除不需要查找的东西:

代码语言:javascript
复制
# 跳过.git和node_moudles目录
find . \( -name ".git" -prune \) -o \( -name "node_modules" -prune \) -o \( -type f -print \)

xargs

xargs命令把从stdin接到的数据重新格式化,作为参数提供给其它命令,紧跟在管道操作符之后,基本形式:

代码语言:javascript
复制
cmd | xargs

把多行输入转换成单行输出:

代码语言:javascript
复制
# 把换行符换成空格
cat test.sh | xargs

把单行输入转换成多行输出:

代码语言:javascript
复制
# 按每行参数数量断开
echo "1 22 3 4 5 6 7" | xargs -n 3

-d指定分隔符,实现字符串split

代码语言:javascript
复制
# split
echo "1,2,3,4" | xargs -d ,
# `-d`参数是GUN扩展,FreeBSD和mac上没有,用其它方法完成
echo "1,2,3,4" | tr , ' '

-I指定替换字符串:

代码语言:javascript
复制
# replace
echo "1 2 3 4" | xargs -n 1 -I {} find {}.txt

find结合xargs

代码语言:javascript
复制
# 查找并删除
find . -type f -name "*.tmp" -print0 | xargs -0 rm -f

这里的-print0xargs -0\0作为分隔符,避免temp file.tmp之类的含有默认分隔符的文件名被拆成两个参数

统计代码行数:

代码语言:javascript
复制
find . -type f -name "*.sh" -print0 | xargs -0 wc -l

对一个参数执行多条命令:

代码语言:javascript
复制
# 与上面的replace作用相同
echo '1\n2\n3\n4' | (while read arg; do find $arg.txt; done)

xargs对每个参数只能执行一条命令,改用子shell中循环读取的话,能在循环体里执行多条命令

P.S.这里的括号是圆括号扩展运算符,开子shell执行括号里的命令,不是前面的条件分组,不要转义括号

tr(translate)

对来自标准输入的字符进行替换,删除和压缩,用来做字符串处理

代码语言:javascript
复制
#  大小写转换
echo 'Ho Hoho hoho' | tr 'a-z' 'A-Z'

如果两个字符集合大小不一样,就把后一个集合用其最后一个字符补足,例如:

代码语言:javascript
复制
# 结果是ABC XXX
echo 'abc xyz' | tr 'a-z' 'A-X'

P.S.定义字符集合的形式是起始字符-终止字符,结果不是一个连续的字符序列的话,就当做3个普通字符

注意:tr只是对输入的每个字符做映射,没有串匹配和替换,是字符级的操作,不是字符序列(字符串)级的

其它常用选项:

代码语言:javascript
复制
# -d删除字符
# 结果是a, a , 579
echo 'hohoa, hoa 123, 4579' | tr -d 'ho0-4'
# -c得到补集,一般与-d结合删除补集里的字符,只保留给定字符集合里的
# 结果是hohoho1234
echo 'hohoa, hoa 123, 4579' | tr -d -c 'ho0-4'
# -s压缩字符(把连续的重复字符换成一个)
# 结果是ha, ha
echo 'hhhhhha, ha' | tr -s 'a-z'

用字符类(character class)作为集合:

代码语言:javascript
复制
# 大小写转换
echo '124abcX1' | tr '[:lower:]' '[:upper:]'

其它字符类可以通过man tr查看

md5sum, sha1sum

这两个命令用来计算校验和,例如:

代码语言:javascript
复制
# 求文件md5
# 结果是`32个字符的16进制串 文件名`
md5sum test.sh

P.S.mac默认没有md5sum, sha1sum,需要额外安装

用md5文件校验

代码语言:javascript
复制
# 用md5文件检查文件是否正确
md5sum -c file.md5

md5deep生成文件夹的md5,需要额外安装(sha1deep与之类似):

代码语言:javascript
复制
# yum安装
yum install md5deep
# 求文件夹的md5
# -r递归,-l生成相对路径(默认是绝对路径)
md5deep -rl dir > dir.md5
# 用所有md5文件校验
md5sum *.md5

sort & uinq

sort命令对行排序,uniq去重,一般配合使用,例如:

代码语言:javascript
复制
# 对file.txt内容每行按字典序排序,并去重
sort file.txt | uniq
# 或者
sort -u file.txt

默认按字典序序升序排序,-n按数值排序,-r降序:

代码语言:javascript
复制
# 如果字母数字都有,字母在前
sort -n file.txt
sort -r file.txt

其它常用选项:

代码语言:javascript
复制
# 检查文件内容是否有序,是否按数值序用-nC
# 返回值为0,表示有序
sort -C file.txt; echo $?
# 按第2列排序
sort -k 2 file.txt
# 按第2个字符到第5个字符排序
sort -k 2,5 file.txt
# 用\0作为分隔符(通过管道结合其它命令时有用)
sort -z file.txt
# 忽略前导空白字符
sort -b file.txt

uniq命令只能用于有序的输入,所以一般结合sort使用:

代码语言:javascript
复制
# 只显示唯一的行(出现多于1次的行都被滤掉)
uniq -u sorted.txt
# 统计各行出现次数
uniq -c sorted.txt
# 找出重复的行
uniq -d sorted.txt

去重也可以指定key

代码语言:javascript
复制
# -s跳过前几个字符,-w指定key的长度
uniq -s 3 -w 2 sorted.txt

P.S.mac没有-w选项

split

split命令用来分割大文件,例如:

代码语言:javascript
复制
# 把data.txt分割成1k的多个文件
split -b 1k data.txt

默认生成xaa, xab, xac...之类的文件名,默认严格按大小拆分,行可能会被截断,甚至一个汉字被拆开

生成的文件名可以手动指定,最后一个参数是前缀,默认是x-a指定后缀长度,其它选项请查看man split

也可以按行分割文件:

代码语言:javascript
复制
# 每个文件10行,文件名为`small.aa, small.ab, small.ac...`
split -l 10 test.sh 'small.'

P.S.原来有这种命令,当时为了拆分sql备份文件,特意找了一个能够编辑大文件的文本编辑器,手动分割的…

P.S.另一个更强大的文件分割命令是csplit,常用来分割日志文件,能够以是否存在指定文本内容为条件拆分

其它小技巧

临时文件命名

Ubuntu,Debian中有tempfile命令,用来生成临时文件名(一个随机字符串),其它环境可以使用RANDOM环境变量,或者当前进程id:

代码语言:javascript
复制
# 取RANDOM环境变量的值
$RANDOM
# 取当前进程id
$$

字符串提取

%, %%, #, ##操作符提供了强大的字符串提取功能:

代码语言:javascript
复制
file=logo.png
# 提取文件名
filename=${file%.*}
echo filename:$filename
# 提取扩展名
ext=${file##*.}
echo ext:$ext

用法如下:

代码语言:javascript
复制
# 从var的值中删掉%右侧通配符所匹配的字符串,从右边向左匹配
${var%.*}
# %%贪婪匹配,会找出最长串,%匹配最短串
${var%.*}# 从var的值中删掉#右侧通配符所匹配的字符串,从左向右匹配
${var#*.}
# 对应的贪婪匹配
${var##*.}

提取扩展名应该用##贪婪匹配,因为file.txt.md5之类的文件名含有多个.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端问问 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • cat(concatenate)
  • find
    • 基本规则
      • 按文件类型搜索
        • 按时间搜索
          • 按文件大小搜索
            • 其它用法
            • xargs
            • tr(translate)
            • md5sum, sha1sum
            • sort & uinq
            • split
            • 其它小技巧
              • 临时文件命名
                • 字符串提取
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档