我遇到过通配符模式和通配符,其中特别让我感兴趣的是[!]
。
此构造类似于
[!]
构造,不同之处在于它不匹配括号内的任何字符,而是匹配任何字符,只要它未在 和 之间[
列出]
。
rm myfile [!192]
我相信上述操作将删除所有文件,但名称中带有 192 的所有文件除外。
然而,我担心文件扩展名的正确使用,特别是在多种情况下。
在这种情况下正确的语法是什么?
rm myfile [!.gif .csv. mp3]
或者
rm myfile [!.gif !.csv !.mp3]
我担心句号可能放错了,所以任何.
当我试图对特定文件进行操作时,带有(肯定是其中任何一个?)的文件就会被操作。
此构造类似于[ ]
构造,不同之处在于它不匹配括号内的任何字符,而是匹配任何字符,只要它未在 和 之间[
列出]
。
(引自http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm)
现在;对我来说,这表明单数!
就足够了,并且其后的所有值都包含在范围内。
答案1
引用man 7 glob
:
An expression "[!...]" matches a single character, namely any character
that is not matched by the expression obtained by removing the first '!' from it.
(Thus, "[!]a-]" matches any single character except ']', 'a' and '-'.)
强调单个字符此处的部分[]
不能用于 Bash 模式匹配中的整个字符串。
bash
的括号扩展可用于匹配字符串,但是没有办法(据我所知)对其进行否定。例如
1.{gif,csv,mp3}
扩展为
1.gif 1.csv 1.mp3
无论这些文件是否存在。
作为收费指出shopt
可用于启用扩展模式匹配运算符,其中之一是!()
。运行后shopt -s extglob
,例如
1.!(gif|csv|mp3)
扩展为
1.jpg 1.bmp 1.png
如果这些文件存在于当前目录中。有关详细信息,请阅读man bash
(扩展/路径名扩展部分)和路径名扩展(通配符)。
对于您要尝试做的事情,我总是会使用find
,它提供否定和更多内容,例如以以下方式:
find . -maxdepth 1 -type f ! -name "*.gif" -a ! -name "*.csv" -a ! -name "*.mp3"
这只是列出了调查结果,如果你想删除它们,只需附加-delete
选项到最后命令。与删除操作一样:务必先仔细检查。
find
提供了大量有用的选项,解释得很好man find
。
答案2
我认为你误解了括号的用法。[abc]
匹配一字符a
,b
或c
.[!abc]
匹配一性格不是 a
或。b
因此c
命令
rm myfile [192]
将删除myfile
文件1
,9
并且2
因为 myfile 和括号之间有空格。相比之下,命令
rm myfile[192]
将删除文件myfile1
,myfile9
并且myfile2
。
答案3
括号[
]
表示字符类。括号内的任何单个字符都可能匹配给定的位置。因此
file[192]
匹配三个可能的名称:
file1
file2
file9
确实如此不是匹配file192
,因为它只处理之后的单个字符file
。
我们还可以在括号中使用范围。[0-9]
匹配给定位置的任何单个数字。对于两位数字,我们需要[0-9][0-9]
。对于后跟大写字母的数字,我们可以使用[0-9][A-Z]
...
!
表示否定。
file[!192]
file
将匹配在except1
或9
或之后包含任何单个字符的文件2
。例如,它将匹配file7
andfiles
和file%
(以及许多其他字符),但是不是 file192
,因为其中有两个额外的字符。
对于您的用例,我建议使用find
而不是[!]
。它有一个not
运算符。
这也是递归,这意味着它默认进入所有子目录。-maxdepth 1
如果您愿意,可以使用 将其限制为当前目录。 Shell 通配符(通配符)是非递归的(尽管**
可以使用 启用递归通配符)。
假设您不想避免删除符号链接,我们可以添加-type d
到否定测试中以避免删除任何目录。感谢 Eliah Kagan 的建议。
find /path -maxdepth 1 -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \)
如果你看到了你想要的东西,你可以再次运行命令-delete
find /path -maxdepth 1 -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \) -delete