假设我想复制一个目录的内容,不包括名称包含单词“音乐”的文件和文件夹。
cp [exclude-matches] *Music* /target_directory
应该用什么来代替[排除匹配]来实现这一点?
假设我想复制一个目录的内容,不包括名称包含单词“音乐”的文件和文件夹。
cp [exclude-matches] *Music* /target_directory
应该用什么来代替[排除匹配]来实现这一点?
当前回答
我还没有在这里看到一个不使用extglob, find或grep的技巧是将两个文件列表视为集合,并使用comm对它们进行“diff”:
comm -23 <(ls) <(ls *Music*)
Comm比diff更可取,因为它没有额外的麻烦。
返回集合1,ls中不存在于集合2,ls *Music*中的所有元素。这需要两个集合都按顺序排序才能正常工作。ls和glob展开没有问题,但如果使用find之类的东西,一定要调用sort。
comm -23 <(find . | sort) <(find . | grep -i '.jpg' | sort)
可能有用。
其他回答
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可以用来控制这个。
如果您想避免使用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, find或grep的技巧是将两个文件列表视为集合,并使用comm对它们进行“diff”:
comm -23 <(ls) <(ls *Music*)
Comm比diff更可取,因为它没有额外的麻烦。
返回集合1,ls中不存在于集合2,ls *Music*中的所有元素。这需要两个集合都按顺序排序才能正常工作。ls和glob展开没有问题,但如果使用find之类的东西,一定要调用sort。
comm -23 <(find . | sort) <(find . | grep -i '.jpg' | sort)
可能有用。
在bash中,shopt -s extglob的替代方法是GLOBIGNORE变量。它并不是更好,但我发现它更容易记住。
下面的例子可能就是最初的海报想要的:
GLOBIGNORE="*techno*"; cp *Music* /only_good_music/
完成后,取消设置GLOBIGNORE,以便能够在源目录中rm *techno*。
你也可以使用一个非常简单的for循环:
for f in `find . -not -name "*Music*"`
do
cp $f /target/dir
done