Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在unix/linux shell中进行模式匹配时,如何使用反向或负通配符?_Bash_Shell_Pattern Matching_Glob - Fatal编程技术网

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

Bash 在unix/linux shell中进行模式匹配时,如何使用反向或负通配符?,bash,shell,pattern-matching,glob,Bash,Shell,Pattern Matching,Glob,假设我要复制目录的内容,但不包括名称中包含单词“Music”的文件和文件夹 cp [exclude-matches] *Music* /target_directory 要做到这一点,应该用什么来代替[排除匹配项]?可以用find找到一个解决方案 $ mkdir foo bar $ touch foo/a.txt foo/Music.txt $ find foo -type f ! -name '*Music*' -exec cp {} bar \; $ ls bar a.txt Find有

假设我要复制目录的内容,但不包括名称中包含单词“Music”的文件和文件夹

cp [exclude-matches] *Music* /target_directory

要做到这一点,应该用什么来代替[排除匹配项]?

可以用find找到一个解决方案

$ mkdir foo bar
$ touch foo/a.txt foo/Music.txt
$ find foo -type f ! -name '*Music*' -exec cp {} bar \;
$ ls bar
a.txt
Find有很多选项,您可以非常详细地了解包含和排除的内容


编辑:Adam在评论中指出这是递归的。查找选项mindepth和maxdepth在控制这方面很有用。

可以使用find找到一个解决方案

$ mkdir foo bar
$ touch foo/a.txt foo/Music.txt
$ find foo -type f ! -name '*Music*' -exec cp {} bar \;
$ ls bar
a.txt
Find有很多选项,您可以非常详细地了解包含和排除的内容

编辑:Adam在评论中指出这是递归的。查找选项mindepth和maxdepth在控制这方面很有用。

不是在bash中(据我所知),而是:

我知道这并不完全是您想要的,但它将解决您的示例。

不是在bash中(我知道),而是:


我知道这并不完全是您想要的,但它将解决您的示例。

您也可以使用非常简单的
for
循环:

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

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

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

在Bash中,您可以通过如下方式启用
extglob
选项来实现这一点(当然,将
ls
替换为
cp
并添加目标目录)

您可以稍后使用禁用extglob

shopt -u extglob

在Bash中,您可以通过如下方式启用
extglob
选项来实现这一点(当然,将
ls
替换为
cp
并添加目标目录)

您可以稍后使用禁用extglob

shopt -u extglob

如果您想避免使用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/

如果您想避免使用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/

extglob
shell选项在命令行中提供了更强大的模式匹配功能

您可以使用
shopt-s extglob
打开它,然后使用
shopt-u extglob
关闭它

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

$ shopt -s extglob
$ cp !(*Music*) /target_directory
完整可用的ext结束的globbing操作符是(摘自
manbash
):

如果使用shopt内置函数启用extglob shell选项,则会有几个扩展 识别模式匹配运算符。模式列表是由一个或多个模式组成的列表,这些模式由|分隔。组合模式可以使用以下一个或多个子模式形成:

  • ?(模式列表)
    匹配给定模式的零个或一个匹配项
  • *(图案列表)
    匹配给定模式的零次或多次出现
  • +(图案列表)
    匹配给定模式的一个或多个匹配项
  • @(图案列表)
    匹配给定模式之一
  • !!(图案列表)
    匹配除一个给定模式之外的任何模式
因此,例如,如果要列出当前目录中不是
.c
.h
文件的所有文件,您可以执行以下操作:

$ ls -d !(*@(.c|.h))
当然,正常的外壳全球化是有效的,因此最后一个示例也可以写成:

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

extglob
shell选项在命令行中提供了更强大的模式匹配功能

您可以使用
shopt-s extglob
打开它,然后使用
shopt-u extglob
关闭它

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

$ shopt -s extglob
$ cp !(*Music*) /target_directory
完整可用的ext结束的globbing操作符是(摘自
manbash
):

如果使用shopt内置函数启用extglob shell选项,则会有几个扩展 识别模式匹配运算符。模式列表是由一个或多个模式组成的列表,这些模式由|分隔。组合模式可以使用以下一个或多个子模式形成:

  • ?(模式列表)
    匹配给定模式的零个或一个匹配项
  • *(图案列表)
    匹配给定模式的零次或多次出现
  • +(图案列表)
    匹配给定模式的一个或多个匹配项
  • @(图案列表)
    匹配给定模式之一
  • !!(图案列表)
    匹配除一个给定模式之外的任何模式
因此,例如,如果要列出当前目录中不是
.c
.h
文件的所有文件,您可以执行以下操作:

$ ls -d !(*@(.c|.h))
当然,正常的外壳全球化是有效的,因此最后一个示例也可以写成:

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

这样就可以完全排除“音乐”

cp -a ^'Music' /target
这个和那个用来排除音乐之类的东西

cp -a ^\*?'complete' /target
cp -a ^'complete'?\* /target

这样就可以完全排除“音乐”

cp -a ^'Music' /target
这个和那个用来排除音乐之类的东西

cp -a ^\*?'complete' /target
cp -a ^'complete'?\* /target

我个人的偏好是使用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

我个人的偏好是使用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

以下作品列出了当前目录中的所有
*.txt
文件,除了