欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

bash的brace expansion(大括号扩展)功能

程序员文章站 2022-05-15 20:25:37
...

刚刚在执行find搜索命令时,报错了。。

$ find ./ -maxdepth 1 -type f -name *.trace
find: paths must precede expression: eEEProIfconfig.trace
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

网上查了下,原来是在使用正则搜索多个文件时,正则PATTERN表达式需要加上引号(单引号和双引号都可以)。

$ find ./ -maxdepth 1 -type f -name "*.trace"
./1.trace
./2.trace
./3.trace

其间网上看到这么两条指令:

$find /data/ -type f -name"*.txt" -exec cp {} /tmp \;
$find /var/www/ -name file -exec cp {}{,.bak} \; 递归备份文件

对其中cp指令后面的空白大括号比较疑惑。带着疑问网上搜索了下,得知{}大括号里的内容为find命令找到的结果

@astrotycoon 的《bash之花括号展开(brace expansion)》这篇博文详细介绍了bash中花括号(大括号)的扩展。
其中下图非常有意思,展示了bash shell的扩展顺序:
bash的brace expansion(大括号扩展)功能


回到花括号扩展的问题上来,

花括号展开的定义(brace expansion)

花括号扩展有时在别的书籍中也被称为大括号扩展,是可以让bash生成任意字符串的一种扩展功能。它与后面会提到的“路径扩展”非常相似,唯一不同的是生成的字符串可以是不存在的路径或者文件名
在bash中,花括号扩展在诸多扩展中的优先级最高,因此像类似于echo {a,b}$PATH的语句在完成花括号扩展之后的结果应该为a$PATH和 b$PATH,而对PATH环境变量的扩展需要到后续的“参数和变量扩展”阶段才开始。

花括号扩展的两种格式

第一类格式为

preamble+{string1,string2,...,stringN}+postscript

左右的花括号是必须的,中间的字符串列表分别由逗号隔开,注意逗号前后不能有空格,如果string中有空格,则需要用单引号或者双引号括起来。

bash在实际扩展时,会将preamble和花括号种的所有字符串(按照从左到右的顺序)相连,最后分别加上postscript。

此外,花括号中间至少有一个逗号,否则bash不会认为这是括号扩展,例如echo {money}就只会输出{money},想要输出money,需要改为echo {money,},如下:

$echo {money}
{money}
$echo {money,}
money
$ echo sp{el,il,al}l
spell spill spall
$ echo sp{el,il, al}l  //al之前有空格,则原样输出
sp{el,il, al}l

第二类格式为

preamble+{<START>..<END>[..<INCR>]}+postscript

其中<START>..<END>组合而成的表达式术语叫做序列表达式(sequence expression),表示一个特定的范围。当<START>和<END>是数字时,代表的是数字范围;当<START>和<END>是单个字母时,代表的是字符范围(默认LC_ALL字符排序)。<START>和<END>必须同为数字或者字母,否则bash不认为是花括号扩展,而是原样输出。

其中的<INCR>是可选的,代表的是区间范围的递增数,它必须是数字;如果不指定<INCR>,那么默认是1或者是-1,具体是1还是-1,要看前面区间范围是递增的还是递减的。例如:

$ echo {0..10..2}
0 2 4 6 8 10

另外,当和是数字时,我们可以通过在数字前面加0来使输出结果的长度保持一致,例如:

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
$ echo {01..10}
01 02 03 04 05 06 07 08 09 10
$ echo {001..10}
001 002 003 004 005 006 007 008 009 010


下面再举几个例子

例子1:

//将find搜索结果来填充空白大括号
$find /data/ -type f -name"*.txt" -exec cp {} /tmp \;
//将/data/目录下的所有.txt文件复制到/tmp/目录下

注意,这条指令最后的 ; 冒号 是必须要有的。

例子2:

$cp filename{,.bak}
//注意花括号边并没有空格,否则就不是扩展了,变成拷贝为{,.bak}文件了。
//这个命令是用来把filename备份成filename.bak,等同于命令 
$cp filename filename.bak 

例子3:

$touch file{1,2,3,4}.txt
$ls
file1.txt  file2.txt  file3.txt  file4.txt



Reference:

find命令结合cp的使用

cp filename{,bak} , find /var/www/ -name file -exec cp {}{,.bak} ; 递归备份文件,大括号扩展:cp和mv搭配{,}在shell作用,cp 快速备份 bash{} 扩展。

bash之花括号展开(brace expansion)

bash shell 大括号扩展

相关标签: bash shell