当前位置:  开发笔记 > 编程语言 > 正文

在unix/linux shell中进行模式匹配时,如何使用反向或负向通配符?

如何解决《在unix/linuxshell中进行模式匹配时,如何使用反向或负向通配符?》经验,为你挑选了7个好方法。

假设我想复制目录的内容,不包括名称中包含"音乐"一词的文件和文件夹.

cp [exclude-matches] *Music* /target_directory

什么应该代替[exclude-matches]来实现这个目标?



1> Vinko Vrsalo..:

在Bash中,您可以通过启用该extglob选项来完成此操作(当然,替换lscp并添加目标目录)

~/foobar> shopt extglob
extglob        off
~/foobar> ls
abar  afoo  bbar  bfoo
~/foobar> ls !(b*)
-bash: !: event not found
~/foobar> shopt -s extglob  # Enables extglob
~/foobar> ls !(b*)
abar  afoo
~/foobar> ls !(a*)
bbar  bfoo
~/foobar> ls !(*foo)
abar  bbar

您可以稍后禁用extglob

shopt -u extglob


我喜欢这个功能:`ls/dir/*/!(base*)`
为什么默认禁用?
你如何包括一切(*)并排除!(b*)?
除了`foo`之外,你会怎么匹配以`f`开头的一切?
shopt -o -u histexpand如果你需要查找带有惊叹号的文件 - 默认情况下,默认情况下,extglob是关闭的,这样它就不会干扰histexpand,在文档中它解释了为什么会这样.匹配以f开头的所有内容除了foo:f!(oo),当然'food'仍然匹配(你需要f!(oo*)来阻止以'foo'开头的东西,或者,如果你想要摆脱以'.foo'结尾的某些内容使用!(*.foo),或者前缀:myprefix!(*.foo)(匹配myprefixBLAH但不匹配myprefixBLAH.foo)

2> tzot..:

extglob外壳选项可以让你在命令行更强大的模式匹配.

你打开它shopt -s extglob,然后关闭它shopt -u extglob.

在您的示例中,您最初会执行以下操作:

$ shopt -s extglob
$ cp !(*Music*) /target_directory

全部可用的ext结束的glob bing运算符(摘自man bash):

如果使用内置shopt启用了extglob shell选项,则会识别多个扩展模式匹配运算符.在以下描述中,模式列表是由|分隔的一个或多个模式的列表.可以使用以下子模式中的一个或多个来形成复合图案:

?(pattern-list)
匹配给定模式的零次或一次

*(pattern-list)
匹配给定模式的零次或多次出现

+(pattern-list)
匹配给定模式的一个或多个实例

@(pattern-list)
匹配给定模式之一

!(pattern-list)
匹配除给定模式之外的任何内容

因此,例如,如果要列出当前目录中不是.c.h文件的所有文件,您可以执行以下操作:

$ ls -d !(*@(.c|.h))

当然,正常的shell globing工作,所以最后一个例子也可以写成:

$ ls -d !(*.[ch])


@Koveras用于`.c`或`.h`文件之一是目录的情况.

3> ejgottl..:

不是bash(我知道),但是:

cp `ls | grep -v Music` /target_directory

我知道这不是你想要的,但它会解决你的例子.


只有当stdout是终端时.在管道中使用时,ls每行打印一个文件名.
无论如何你可以使用ls -1
它不适用于包含空格(或其他白色spcace字符)的文件名.

4> Steve..:

如果你想避免使用exec命令的mem成本,我相信你可以用xargs做得更好.我认为以下是一种更有效的替代方案

find foo -type f ! -name '*Music*' -exec cp {} bar \; # new proc for each exec



find . -maxdepth 1 -name '*Music*' -prune -o -print0 | xargs -0 -i cp {} dest/



5> mivk..:

在bash中,的替代方法shopt -s extglobGLOBIGNOREvariable。并不是真的更好,但是我发现它更容易记住。

原始海报想要的示例可能是:

GLOBIGNORE="*techno*"; cp *Music* /only_good_music/

完成后,unset GLOBIGNORE就可以rm *techno*在源目录中了。



6> mipadi..:

您还可以使用一个非常简单的for循环:

for f in `find . -not -name "*Music*"`
do
    cp $f /target/dir
done



7> 小智..:

我个人的偏好是使用grep和while命令.这允许您编写功能强大且可读的脚本,确保您最终完成您想要的操作.另外,通过使用echo命令,您可以在执行实际操作之前执行空运行.例如:

ls | grep -v "Music" | while read filename
do
echo $filename
done

将打印出您最终要复制的文件.如果列表正确,则下一步是使用copy命令替换echo命令,如下所示:

ls | grep -v "Music" | while read filename
do
cp "$filename" /target_directory
done

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有