说我想复制一个目录不包括文件和文件夹名称中包含单词“音乐”的内容。
cp [exclude-matches] *Music* /target_directory
应该在的地方[排除百搭]的去怎么做到这一点?
说我想复制一个目录不包括文件和文件夹名称中包含单词“音乐”的内容。
cp [exclude-matches] *Music* /target_directory
应该在的地方[排除百搭]的去怎么做到这一点?
在bash,那么你可以通过启用做extglob
选项,就像这样(取代ls
与cp
并加入目标目录,当然)
~/foobar> shopt -s extglob
~/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
该extglob
外壳选项可以让你在命令行更强大的模式匹配。
你打开它shopt -s extglob
,并与关闭它shopt -u extglob
。
在你的榜样,你会做初步:
$ shopt -s extglob
$ cp !(*Music*) /target_directory
全部可用分机结束水珠兵运营商(摘自man bash
):
如果extglob外壳选择是使用内建命令shopt启用,几个扩展模式匹配运营商的认可。 在以下描述中,轻拍燕鸥列表是由一个分隔的一个或多个模式的列表|。 复合模式可以使用一个或多个下列子图案形成:
- ?(模式列表)
匹配零个或一个发生所述给定图案的- *(模式列表)
匹配零和或多个给定模式- +(模式列表)
匹配给定模式中的一个或多个出现- @(模式列表)
匹配给定的模式之一- !(模式列表)
匹配任何东西,除了给定的模式之一
因此,举例来说,如果你想列出所有在当前目录中不属于文件.c
或.h
文件,你会怎么做:
$ ls -d !(*@(.c|.h))
当然,一般的外壳globing作品,所以最后一个例子也可以写成:
$ ls -d !(*.[ch])
未在bash(我知道的),但是:
cp `ls | grep -v Music` /target_directory
我知道这不正是你要找的,但它会解决你的榜样。
如果你想避免使用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/
在bash中,替代shopt -s extglob
是GLOBIGNORE
变量 。 这不是真的好,但我觉得它更容易记住。
可能是楼主想要的东西的一个例子:
GLOBIGNORE="*techno*"; cp *Music* /only_good_music/
完成后, unset GLOBIGNORE
能够rm *techno*
源目录。
你也可以使用一个非常简单for
循环:
for f in `find . -not -name "*Music*"`
do
cp $f /target/dir
done
我个人的偏好是使用grep和同时命令。 这可以写出功能强大,可读的脚本,确保你最终究竟做你想要什么。 此外,通过使用echo命令就可以进行实际操作之前进行试运行。 例如:
ls | grep -v "Music" | while read filename
do
echo $filename
done
将打印出来,你最终会复制这些文件。 如果该列表是正确的下一步是简单地复制命令代替echo命令如下:
ls | grep -v "Music" | while read filename
do
cp "$filename" /target_directory
done
这其中的一个解决方案可以与find找到。
$ mkdir foo bar
$ touch foo/a.txt foo/Music.txt
$ find foo -type f ! -name '*Music*' -exec cp {} bar \;
$ ls bar
a.txt
查找有相当多的选项,你可以得到你所包括和排除非常具体。
编辑:亚当在评论中指出,这是递归的。 查找选项mindepth和MAXDEPTH可以在控制这个有用。
我还没有看到这里还没有使用特技extglob
, find
,或者grep
是处理两个文件列表作为集和“差异”使用这些comm
:
comm -23 <(ls) <(ls *Music*)
comm
是在最好diff
,因为它没有多余的残余。
这将返回集1的所有元件ls
,那是不是也中集2, ls *Music*
。 这既需要设置要在排序才能正常工作。 对于没有问题ls
和水珠扩张,但如果你正在使用类似find
,一定要调用sort
。
comm -23 <(find . | sort) <(find . | grep -i '.jpg' | sort)
潜在有用的。
下面的工作列出了所有*.txt
文件在当前目录下,除了那些以数字开头。
这部作品在bash
, dash
, zsh
和所有其他POSIX兼容的炮弹。
for FILE in /some/dir/*.txt; do # for each *.txt file
case "${FILE##*/}" in # if file basename...
[0-9]*) continue ;; # starts with digit: skip
esac
## otherwise, do stuff with $FILE here
done
在一个线条图案/some/dir/*.txt
将导致for
循环遍历所有的文件/some/dir
名称以结束.txt
。
在两个线路的情况下,语句用来淘汰不需要的文件。 -在${FILE##*/}
表达剥掉从文件名(这里的任何领先的目录名称组件/some/dir/
),以便patters可以匹配只针对文件的基本名称。 (如果你只淘汰基于后缀文件名,可以缩短这$FILE
代替。)
三线,匹配的所有文件case
模式[0-9]*
)线将被跳过(在continue
语句跳转到的下一个迭代for
循环)。 -如果你愿意,你可以做一些更有趣的有,例如像使用跳过不以字母开头的所有文件(AZ) [!az]*
,或者你可以使用多种方式来跳过几种文件名如[0-9]*|*.bak
跳过这两个文件.bak
文件和文件,不以数字开头。
这将做到这一点正好除外“音乐”
cp -a ^'Music' /target
这和排除喜欢音乐的东西?*或*?音乐
cp -a ^\*?'complete' /target
cp -a ^'complete'?\* /target