Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I often want to do some variant of this idiom:

$ mkdir 2010
$ svn mv * 2010

Of course, I get an error because the glob matches 2010 as well:

svn: Cannot copy path '2010' into its own child '2010/2010'

Is there a way to replace "svn mv * 2010" with a different one-liner that does the right thing?

share|improve this question
    
This is not a question specific to svn, it applies to vanilla mv as well. However, with mv, mv * newdir works for me, albeit with an error. –  crazy2be May 28 '11 at 1:38
add comment

3 Answers

up vote 11 down vote accepted

Under ksh, bash or zsh:

svn mv !(2010) 2010

Under bash, you need to run shopt -s extglob first (put it in your ~/.bashrc). Under zsh, you need to run setopt -o ksh_glob first (put it in your ~/.zshrc).

This doesn't move dot files (files whose name begins with .). If you have some, move them separately. Take care to exclude the .svn directory if you have one. In ksh or zsh:

svn mv !(2010) .!(svn) 2010

In bash, this is more complicated because you also need to explicitly exclude . and ...

svn mv !(2010) .!(svn|.|) 2010

Zsh also has a different, shorter syntax, which requires running setopt -o extended_glob first (again, put this in ~/.zshrc):

svn mv {^,}2010

First brace expansion comes into play, resulting in svn mv ^2010 2010. Then the pattern ^2010 (a shortcut for “files matching * but not 2010”) is expanded.

If you have a .svn directory, you'll need to exclude it from the move. This is ok by default, as .svn is not matched by * (it's a dot file). However, there are complications:

  • If you've set the glob_dots option, you'll need to exclude .svn as well:

    svn mv !(2010|.svn) 2010             # requires setopt ksh_glob
    svn mv *~(.svn|2010) 2010            # requires setopt extended_glob
    
  • If you have dot files and you haven't set glob_dots, you'll need to move them separately:

    svn mv {^,}2010
    svn mv .*~.svn 2010
    

    To do it in one go:

    svn mv *~(.svn|2010)(D) 2010
    

Another way that would work in zsh in this case (if you have no subdirectories) is svn mv *(.D) 2010, to match only regular files (.) including dot files (D).

share|improve this answer
add comment

ZSH has a helpful glob operator to match everything except a given name, ^. So this would work (but it's ZSH specific, and you need to setopt extendedglob first):

$ svn mv ^2010 2010
share|improve this answer
    
I've known about the !() syntax that works with zsh. How does the ^ syntax differ? It doesn't work in my shell, what option would I need to set to enable it? –  Caleb May 28 '11 at 9:45
    
@Caleb Sorry, I thought it was on by default, but apparently you need to setopt extendedglob. I didn't know about !(), it sounds like a more cross-shell way to do it –  Michael Mrozek May 28 '11 at 18:42
    
svn mv {^,}2010 to avoid typing the directory name twice –  Gilles Feb 6 '13 at 19:07
add comment

If your files have “tame” names (no whitespace, unprintable characters or \[?*):

svn mv $(ls | grep -vx 2010) 2010
share|improve this answer
2  
Files cannot be trusted to have "tame" names. Ever :) The shell glob solutions presented for bash and zsh neatly sidestep this issue. –  Caleb May 28 '11 at 9:42
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.