保存 我有一系列名为{1..40}0.txt
(所以10.txt
到400.txt
10)的文件:
➜ ls
10.txt 60.txt 110.txt 160.txt 210.txt 260.txt 310.txt 360.txt
20.txt 70.txt 120.txt 170.txt 220.txt 270.txt 320.txt 370.txt
30.txt 80.txt 130.txt 180.txt 230.txt 280.txt 330.txt 380.txt
40.txt 90.txt 140.txt 190.txt 240.txt 290.txt 340.txt 390.txt
50.txt 100.txt 150.txt 200.txt 250.txt 300.txt 350.txt 400.txt
我想删除所有介于 100 到 300 之间但不能被 100 整除的文件。即。离开{1..9}0.txt
,100.txt
,200.txt
,3{1..9}0.txt
:
rm 110.txt 130.txt 150.txt 170.txt 190.txt 220.txt 240.txt 260.txt 280.txt
120.txt 140.txt 160.txt 180.txt 210.txt 230.txt 250.txt 270.txt 290.txt
在 zsh 中,我可以对 100 到 300 via 之间的文件进行 glob <100-300>.txt
,并且可以对那些可被 100 via 整除的文件进行 glob ^(*00).txt
(使用extendedglob
设置的选项)。
是否可以将文件全局模式一个接一个地链接起来?因此,glob 100-300 个文件,然后 glob 剩余的文件查找那些没有00
? 的文件。
请注意,在单个 glob 中执行此操作的方法是<100-300>.txt~(*00).txt
,其中~
提供排除(请参阅zsh 文档)。编辑:打全球高尔夫,我可以把它简化为<10-30>0*~*00*
.
答案1
$ touch {10..400..10}.txt
$ print -rC1 -- <100-300>.txt(e['(( $REPLY:r % 100 != 0 ))'])
110.txt
120.txt
130.txt
140.txt
150.txt
160.txt
170.txt
180.txt
190.txt
210.txt
220.txt
230.txt
240.txt
250.txt
260.txt
270.txt
280.txt
290.txt
以上touch
创建了文件。
下一行的位<100-300>.txt
选择以 100 到 300 之间的数字开头的文件。
glob 限定符 ,(e['(( $REPLY:r % 100 != 0 ))'])
选择“根”(不带扩展名的名称,具有 via :r
)不能被 100 整除的文件名。
当然,您也可以通过 glob 限定符来完成这一切:
*.txt(e['(( r=$REPLY:r, r >= 100 && r <= 300 && r % 100 != 0 ))'])
答案2
如果通过一个接一个地链接团,您的意思相当于grep pattern | grep another-pattern
or grep pattern | grep -v excluded-pattern
,即获取一个匹配文件列表,然后在第二次迭代中进一步细化该列表,您将使用${array:#exclude-pattern}
and${(M)array:#only-pattern}
运算符:
list=(*(N)) # all non-hidden files
list=(${(M)list:#<100-300>.txt}) # only retain the ones matching that pattern
list=(${list:#*00.txt}) # remove the ones matching that other pattern
否则,就您而言,最明显的方法(无论如何对我来说)是使用~
AND-NOT(例外)运算符(需要extendedglob
)。您也可以这样做:
list=((<100-300>~*00).txt(N))
“连锁”全局运算符有:
- OR:(
|
就像在 ERE 中一样,但仅在(...)
as内部|
也是管道运算符):(patternA|patternB)
- 与非:(
~
与extendedglob
):patternA~patternB
- NOT:(
^
带有extendedglob
) 或!(pattern)
(带有kshglob
和不带histexpand
或带有不同的字符作为 的第一个字符$HISTCHARS
) - AND:(
~^
即 AND-NOT-NOT,与extendedglob
),或!(!(patternA)|!(patternB))
与kshglob
。
作为@Kusalananda 已经表明,您还可以使用e
glob 限定符根据任意 shell 代码的执行进一步细化 glob 选择。
你甚至可以做这样的事情:
list=(*(Ne['[[ $REPLY = <100-300>.txt ]] && [[ $REPLY != *00.txt ]]']))