“Mkdir foo; svn mv * foo ”

9

Muitas vezes eu quero fazer alguma variante desse idioma:

$ mkdir 2010
$ svn mv * 2010

Obviamente, recebo um erro porque o glob também corresponde a 2010:

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

Existe uma maneira de substituir "svn mv * 2010"por uma linha única que faça a coisa certa?

Lorin Hochstein
fonte
Esta não é uma pergunta específica para o svn, mas também para a baunilha mv. No entanto, com mv, mv * newdirfunciona para mim, embora com um erro.
crazy2be

Respostas:

14

Sob ksh, bash ou zsh:

svn mv !(2010) 2010

No bash, você precisa executar shopt -s extglobprimeiro (coloque-o no seu ~/.bashrc). No zsh, você precisa executar setopt -o ksh_globprimeiro (coloque-o no seu ~/.zshrc).

Isso não move arquivos de ponto (arquivos cujo nome começa com .). Se você tiver alguns, mova-os separadamente. Tome cuidado para excluir o .svndiretório, se você tiver um. Em ksh ou zsh:

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

No bash, isso é mais complicado porque você também precisa excluir .e explicitamente ...

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

O Zsh também possui uma sintaxe diferente e mais curta, que requer a execução setopt -o extended_globprimeiro (novamente, coloque isso em ~/.zshrc):

svn mv {^,}2010

A primeira expansão da cinta entra em jogo, resultando em svn mv ^2010 2010. Em seguida, o padrão ^2010(um atalho para "arquivos correspondentes, *mas não 2010") é expandido.

Se você tiver um .svndiretório, será necessário excluí-lo da movimentação. Isso está ok por padrão, pois .svnnão é correspondido por *(é um arquivo de ponto). No entanto, existem complicações:

  • Se você definiu a glob_dotsopção, também precisará excluir .svn:

    svn mv !(2010|.svn) 2010             # requires setopt ksh_glob
    svn mv *~(.svn|2010) 2010            # requires setopt extended_glob
  • Se você possui arquivos de ponto e não o configurou glob_dots, precisará movê-los separadamente:

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

    Para fazê-lo de uma só vez:

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

Outra maneira que funcionaria no zsh nesse caso (se você não tiver subdiretórios) é svn mv *(.D) 2010corresponder apenas aos arquivos regulares ( .), incluindo os arquivos de ponto ( D).

Gilles 'SO- parar de ser mau'
fonte
3

O ZSH possui um operador glob útil para combinar tudo, exceto um nome ^,. Portanto, isso funcionaria (mas é específico ao ZSH, e você precisa setopt extendedglobprimeiro):

$ svn mv ^2010 2010
Michael Mrozek
fonte
Eu sei sobre a !()sintaxe que funciona com zsh. Como a ^sintaxe difere? Ele não funciona no meu shell, que opção eu precisaria definir para habilitá-lo?
Caleb
@ Caleb Desculpe, eu pensei que era por padrão, mas aparentemente você precisa setopt extendedglob. Eu não sabia !(), parece uma maneira mais concisa de fazê-lo
Michael Mrozek
svn mv {^,}2010evitar digitar o nome do diretório duas vezes
Gilles 'SO- stop be evil'
0

Se seus arquivos tiverem nomes "mansos" (sem espaço em branco, caracteres não imprimíveis ou \[?*):

svn mv $(ls | grep -vx 2010) 2010
Chris Ting
fonte
2
Os arquivos não podem ser confiáveis ​​para terem nomes "mansos". Ever :) As soluções shell glob apresentadas para o bash e o zsh evitam claramente esse problema.
Caleb