我经常想做这个习语的一些变体:
$ mkdir 2010
$ svn mv * 2010
当然,我收到错误,因为 glob 也匹配 2010:
svn: Cannot copy path '2010' into its own child '2010/2010'
有没有一种方法可以"svn mv * 2010"
用不同的单衬来代替,从而起到正确的作用?
答案1
在 ksh、bash 或 zsh 下:
svn mv !(2010) 2010
在 bash 下,您需要shopt -s extglob
先运行(将其放入您的~/.bashrc
)。在 zsh 下,您需要setopt -o ksh_glob
先运行(将其放入您的~/.zshrc
)。
这不会移动点文件(名称以 开头的文件.
)。如果有,请将它们分开移动。.svn
如果有目录,请注意排除该目录。在 ksh 或 zsh 中:
svn mv !(2010) .!(svn) 2010
在 bash 中,这更加复杂,因为您还需要显式排除.
和..
。
svn mv !(2010) .!(svn|.|) 2010
Zsh 还有一种不同的、更短的语法,需要setopt -o extended_glob
首先运行(再次将其放入~/.zshrc
):
svn mv {^,}2010
第一个大括号扩展开始发挥作用,导致svn mv ^2010 2010
.然后该模式(“文件匹配但不匹配”^2010
的快捷方式)被展开。*
2010
如果您有.svn
目录,则需要将其从移动中排除。默认情况下这是可以的,因为与(它是一个点文件).svn
不匹配。*
然而,也存在一些并发症:
如果您设置了该
glob_dots
选项,则还需要排除.svn
:svn mv !(2010|.svn) 2010 # requires setopt ksh_glob svn mv *~(.svn|2010) 2010 # requires setopt extended_glob
如果您有点文件并且尚未设置
glob_dots
,则需要单独移动它们:svn mv {^,}2010 svn mv .*~.svn 2010
一次性完成:
svn mv *~(.svn|2010)(D) 2010
在这种情况下(如果没有子目录),在 zsh 中工作的另一种方法是svn mv *(.D) 2010
仅匹配常规文件 ( .
),包括点文件 ( D
)。
答案2
ZSH 有一个有用的全局运算符来匹配除给定名称 之外的所有内容^
。所以这可以工作(但它是 ZSH 特定的,你需要setopt extendedglob
首先):
$ svn mv ^2010 2010
答案3
如果您的文件具有“驯服”名称(没有空格、不可打印字符或\[?*
):
svn mv $(ls | grep -vx 2010) 2010