我的Shell脚本中的逻辑或运算

3
我的脚本:
#!/bin/bash

for file in *.ats;
do
    if [[ ("${file}" = THx) || ("${file}" = THy)]]
    then cp $file /home/milenko/procmt
    fi
done

目录中的文件

262_V01_C00_R000_TEx_BL_128H.ats
262_V01_C01_R000_TEy_BL_128H.ats
262_V01_C02_R000_THx_BL_128H.ats
262_V01_C03_R000_THy_BL_128H.ats

我想复制包含 THx 或 THy 的文件,但是文件没有被复制。为什么?

1
cp *_TH[xy]_*.ats /home/milenk/procmt/?根本没有循环的必要。 - Charles Duffy
4个回答

9
我认为你可以完全避免使用循环:

我认为,您可以在此处完全避免循环:

cp *TH[xy]*.ats /home/milenko/procmt

不需要循环遍历结果,然后进行单独比较;单个glob将扩展为您想要的文件列表。

您原始方法存在一些问题:

  • 首先,您试图测试精确匹配,所以条件永远不会成立。
  • 同时,在使用空格时要小心:]]是复合命令[[中的关键字,因此它需要成为一个单独的单词(即被空格包围)。

2
一个注意事项:如果你期望的匹配数量超过了一条命令行所能容纳的范围,那么循环是必须的。此外,极为严谨地说,] 是简单命令 [ 的一个参数,但是 [[ ... ]] 则是使用关键字 [[]] 的复合命令。 - chepner
谢谢,我已经更新了措辞。那么for循环的长度限制比cp命令的长度限制更大吗? - Tom Fenech
1
无论哪种情况,模式都会传递给扩展模式的库函数。对于外部命令,您需要整个结果来构造一个大的参数列表,以传递给exec*系列中的调用。该参数列表的大小受特定于操作系统的大小限制。对于内部命令,shell一直处于控制状态,因此它只需要从结果中一次获取一个文件来处理主体。 - chepner

6
使用扩展通配符进行扩展式匹配怎么样?这样你就可以在for循环中使用它来获取所需的扩展名:

extglob是指扩展通配符。

shopt -s extglob
for file in *TH?(x|y)*.ats; do
   # do things with "$file" ...
done

*TH?(x|y)*.ats会扩展为包含<something> + TH + x或y + <something> + .ats的文件。


你的脚本失败了,因为它有一个拼写错误

if [[ ("${file}" = THx) || ("${file}" = THy)]]
#                                          ^
#                              missing space

这是可以的:

$ d="hi"
$ [[ ($d == hi) || ($d == ha) ]] && echo "yes"
yes

尽管括号是多余的: ```

尽管括号是多余的:

```
$ [[ $d == hi || $d == ha ]] && echo "yes"
yes

1
除非 xy 表示多字符字符串,否则 ?(x|y) 等同于普通模式 [xy] - chepner

5
你的问题指定“包含THx或THy的文件”...但你的代码指定文件名THx或THy。

2
没有符合 *.ats 模式的文件名将会是 THy 或者 THx - Jdamian

4
你可以在glob中使用字符类,例如*TH[xy]*,来检查$file是否包含THxTHy:
for file in *.ats; do
    if [[ $file == *TH[xy]* ]]; then
       cp "$file" /home/milenko/procmt
    fi
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接