文件名通配符 “?” “*” “[]” “[!]”

本文详细介绍了Linux系统中使用文件名通配符的方法,包括单字符匹配元字符‘?’、多字符匹配元字符‘*’、字符范围匹配符‘[]’以及排除范围匹配符‘[!]’的用法。


在使用Linux系统的过程中,许多时候都需要查找一个文件,如果只记住文件名的一部分,查找时就显得非常困难。这是可以考虑使用文件名通配符


单字符匹配元字符“?”


元字符“?”表示匹配文件名中任意一个字符,连续使用多个元字符“?”可以表示多个任意字符

1.使用a?表示以a开头且有两个字符的文件名

#ls -l a?


2.查看当前目录下由字母a和任意两个字符组成的文件名

#ls -l a??


3.查看当前目录下所有第3个字符是c的文件

#ls -l ??c*


######################################################


多字符匹配元字符“*”


元字符“*”表示匹配文件名中的任意字符串。匹配的字符串长度可以是零到一个字符,也可以是长度很长的多个字符组成的字符串


1.查看当前目录下以字母c结尾的所有文件列表

#ls -l *c


2.查看当前目录下以ee开头,并以c结尾的文件列表

#ls -l ee*c


从上诉例子可知,元字符“*”既可以匹配零个字符,也可以匹配多个字符


3.元字符“*”也可以与其他的元字符配合一起使用

查看当前目录中倒数第2个字符是c的所有文件

#ls -l *c?


4.在当前目录中查看第3个字符为字母c组成的所有文件

#ls -l ??c*


######################################################3


字符范围匹配符"[]"


范围匹配符号“[]”通常用于匹配一个字符范围,其表现形式可以是减号"-"表示的字母和数字的范围,也可以使几个字符的组合

1.如果范围匹配符中出现的是几个字符的组合,表示匹配其中的任何一个字符。

例如要在当前目录中查看以字母klsyz中的任意一个开头的所有文件

#ls -l [klsyz]*


2.使用多个通配符可以进行更加复杂的匹配查找。

例如要在当前目录中查看以字母a开头且倒数第2个字符为字母cde中任意一个的所有文件

#ls -l a*[cde]?


3.使用符号“-”可以匹配一个字母或数字范围。

例如要在当前目录下查看文件名中含有数字的所有文件

#ls -l *[0-9]*

上面的命令中[0-9]表示匹配0到9之间的任意数字


4.要查看当前目录下文件名由两个字符组成且第2个字符是字母的所有文件

[a-Z]表示所有小写字母、大写字母

#ls -l ?[a-Z]


[a-Z]表示所有字母,也可以使用[a-zA-Z]表示所有字母


#########################################################33


排除范围匹配符“[!]”


排除范围匹配符“[!]”表示不匹配符号内出现的字符组合或字母子范围。使用时感叹号“!”只能放置在要排除的字符串首


1.要查看当前目录下文件名只有两个字符并以数字开头且第2个字符不是数字的所有文件

#ls -l [0-9][!0-9]


2.要查看当前目录下文件名只有两个字符且两个字符都不是字母的所有文件

#ls -l [!a-Z][!a-Z]

在上面的命令中[!a-Z]表示排除小写字母a-z和大写字母A-Z,即排除所有字母




<think>我们面对两个关键信息: 1. 错误信息:`/bin/bash: line 1: /???/?????*: ambiguous redirect` 2. 用户提供的字符串:`'/???/??? 0</???/?????*'` 首先,我们需要理解这两个字符串的含义以及它们之间的关系。 ## 错误信息分析 之前的错误信息 `ambiguous redirect` 表示在重定向操作中,目标路径(即重定向写入的文件路径)包含了通配符(如`?`和`*`),并且这个通配符匹配到了多个文件,导致Bash无法确定具体要重定向到哪一个文件。 常见的重定向操作符包括: - `>` : 覆盖写入文件 - `>>` : 追加写入文件 - `<` : 从文件读取输入 错误信息中出现的路径是 `/???/?????*`,这显然是一个包含通配符的路径。 ## 新字符串分析:`'/???/??? 0</???/?????*'` 这个字符串看起来像是一个命令行的一部分。我们可以将其分解: - 第一部分:`/???/???` → 这很可能是一个可执行文件的路径,因为路径中使用了通配符来匹配文件名。 - 第二部分:`0<` → 这是输入重定向操作符(标准输入重定向),后面跟着一个路径。 - 第三部分:`/???/?????*` → 这是一个包含通配符的路径,作为输入重定向的来源。 所以整个命令的含义可能是:执行匹配`/???/???`路径的程序,并将匹配`/???/?????*`路径的文件作为标准输入(文件描述符0)重定向给该程序。 ## 错误原因 当Bash执行重定向(无论是输入重定向还是输出重定向)时,它会在执行命令前先进行路径扩展(即通配符扩展)。如果通配符匹配到多个文件,那么重定向的目标就会变得不明确,导致`ambiguous redirect`错误。 在输入重定向`<`中同样适用这一规则。例如,如果`/???/?????*`匹配到多个文件,那么Bash无法确定应该将哪个文件作为输入,因此报错。 ## 示例说明 假设在根目录`/`下有如下文件: - `/bin/ls` - `/bin/cat` - `/tmp/test1.txt` - `/tmp/test2.txt` 当我们执行命令: ```bash /???/??? 0< /???/?????* ``` 1. 路径扩展第一步:`/???/???` - 可能匹配到:`/bin/ls` 和 `/bin/cat`(假设没有其他匹配项) - 因此,Bash会尝试执行第一个匹配到的程序(按字母顺序),比如`/bin/cat`,但注意:如果通配符匹配多个,且没有用引号括起来,则Bash会将所有匹配项作为参数传递给命令(但这里不是参数,而是命令本身!),这会导致错误,因为命令名必须是唯一的。 2. 路径扩展第二步:`/???/?????*` - 可能匹配到:`/tmp/test1.txt`和`/tmp/test2.txt` - 当进行输入重定向时,要求重定向的目标文件必须是单个文件,但这里扩展成了两个文件,因此会出现`ambiguous redirect`错误。 所以,这个错误是由于输入重定向的目标路径`/???/?????*`匹配到了多个文件。 ## 解决方案 1. **避免在重定向路径中使用通配符**:确保重定向的路径是确定的,不包含通配符。 2. **如果必须使用通配符**:可以编写脚本先获取匹配的文件,然后处理多个文件的情况(例如循环处理),但注意输入重定向只能接受一个文件。 对于输入重定向,我们通常只能指定一个输入文件。因此,如果通配符可能匹配多个文件,应该考虑其他方式,例如: ```bash # 假设我们想用cat命令显示多个文件,我们可以直接传递文件名 cat /???/?????* ``` 但是,如果命令要求从标准输入读取,并且我们需要将多个文件的内容依次作为输入,我们可以使用: ```bash cat /???/?????* | command ``` 然而,在原始字符串中,重定向是直接附加在命令后面的,所以我们需要避免在重定向路径中使用通配符。 ## 结论 用户提供的字符串`'/???/??? 0</???/?????*'`表示: - 运行一个路径匹配`/???/???`的程序(可能匹配多个程序,这也会导致问题) - 并将匹配路径`/???/?????*`的文件作为标准输入重定向(文件描述符0)提供给该程序。 错误`ambiguous redirect`是由于输入重定向的目标路径`/???/?????*`匹配到了多个文件。同时,命令路径`/???/???`如果匹配多个,同样会导致错误(但错误信息可能不同,例如会报`too many arguments`或找不到命令)。 因此,我们需要确保: 1. 命令路径扩展后只有一个可执行文件。 2. 输入重定向的路径扩展后也只有一个文件。 否则,Bash会报错。 ## 引用说明 在RHEL6中出现的ssh-copy-id的Ambiguous output redirect错误也是由于类似的原因:在重定向时路径扩展产生了多个匹配[^1]。 [^1]: 参考示例:`{ eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys"` 中,如果`.ssh/authorized_keys`这个路径由于某种原因被扩展成多个文件(例如,当前目录下有名为`.ssh`的文件和`.ssh`目录),则重定向会失败。但通常这个路径是固定的,所以问题可能出在路径名包含空格等特殊字符时没有加引号。然而在用户提供的例子中,问题明确是通配符导致的多匹配。 --- §§相关问题§§ 1. Bash通配符扩展的规则是什么? 2. 如何避免Shell脚本中的路径扩展错误? 3. 除了重定向,还有哪些场景会出现ambiguous错误? 4. 如何在Bash中安全地使用包含特殊字符的文件路径? </think>### 解释 `/???/??? 0</???/?????*` 的含义及关联错误分析 #### 1. **命令结构分解(使用正则表达式)** - **`/???/???`** - 表示一个可执行文件路径,其中: - `/???/`:匹配根目录下任意3字符目录(如 `/bin/`, `/usr/`, `/sbin/`) - `???`:匹配任意3字符文件名(如 `cat`, `ls`, `awk`) - 示例可能的扩展: $$ \begin{align*} &\text{/bin/cat} \\ &\text{/usr/bin/env} \\ &\text{/sbin/lspci} \end{align*} $$ - **`0<`** - 输入重定向操作符,表示将文件内容重定向到标准输入(文件描述符0) - **`/???/?????*`** - 表示输入文件路径: - `/???/`:根目录下任意3字符目录 - `?????*`:至少5字符开头的任意文件名(如 `data.txt`, `config.yaml`) #### 2. **完整命令语义** $$ \boxed{\text{执行路径匹配 } \mathtt{/???/???} \text{ 的程序,将路径匹配 } \mathtt{/???/?????*} \text{ 的文件作为其输入}} $$ - **等价示例**: ```bash /bin/sort 0< /var/data/input_file ``` #### 3. **与 `ambiguous redirect` 错误的关联机制 | 组件 | 错误触发条件 | 错误原因 | |----------------|--------------------------|--------------------------------------------------------------------------| | `/???/???` | 匹配到多个可执行文件 | 系统无法确定执行哪个程序(但错误提示通常不会在此处出现) | | `/???/?????*` | 匹配到多个输入文件 | **触发 `ambiguous redirect`**:重定向目标不唯一(关键错误源)[^1] | | `0<` | 重定向符号位置错误 | 语法错误(但此处位置正确) | #### 4. **错误发生的具体场景** 假设系统存在以下文件: ``` /bin/cat /bin/ls /var/log/app.log /var/data/config.conf ``` 当执行: ```bash /???/??? 0< /???/?????* ``` Bash 扩展路径时: 1. `/???/???` → 匹配 `/bin/cat` 和 `/bin/ls`(系统随机选择其一执行) 2. `/???/?????*` → 匹配 `/var/log/app.log` 和 `/var/data/config.conf` **重定向目标不唯一 → 触发核心错误**: ``` /bin/bash: line 1: /???/?????*: ambiguous redirect ``` #### 5. **根本解决方案** - **避免通配符重定向**: ```bash # 错误:含通配符 command 0< /path/*.input # 正确:明确路径 command 0< /path/specific_file.input ``` - **必须使用通配符时预检查**: ```bash files=( /path/*.input ) if [ ${#files[@]} -eq 1 ]; then command 0< "${files[0]}" else echo "错误:找到多个匹配文件" fi ``` #### 6. **引用场景对照** 在 `ssh-copy-id` 的案例中: ```bash { eval "$GET_ID" ; } | ssh $1 "cat >> .ssh/authorized_keys" ``` 若 `.ssh/authorized_keys*` 意外匹配到多个文件(如备份文件 `authorized_keys.bak`),同样会引发 `Ambiguous redirect`[^1]。这与当前案例的机制完全一致。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值