“Mkdir foo; svn mv * foo ”

9

Ich möchte oft eine Variante dieser Redewendung machen:

$ mkdir 2010
$ svn mv * 2010

Natürlich bekomme ich eine Fehlermeldung, weil der Glob auch mit 2010 übereinstimmt:

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

Gibt es eine Möglichkeit, durch "svn mv * 2010"einen anderen Einzeiler zu ersetzen , der das Richtige tut?

Lorin Hochstein
quelle
Dies ist keine svn-spezifische Frage, sondern auch für Vanille mv. Funktioniert jedoch mit mv, mv * newdirwenn auch mit einem Fehler.
crazy2be

Antworten:

14

Unter ksh, bash oder zsh:

svn mv !(2010) 2010

Unter Bash müssen Sie shopt -s extglobzuerst laufen (legen Sie es in Ihre ~/.bashrc). Unter zsh müssen Sie setopt -o ksh_globzuerst ausführen (in Ihre einfügen ~/.zshrc).

Dadurch werden keine Punktdateien verschoben (Dateien, deren Name mit beginnt .). Wenn Sie welche haben, verschieben Sie sie separat. Achten Sie darauf, das .svnVerzeichnis auszuschließen, falls Sie eines haben. In ksh oder zsh:

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

In bash ist dies komplizierter, da Sie auch explizit .und ausschließen müssen ...

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

Zsh hat auch eine andere, kürzere Syntax, die setopt -o extended_globzuerst ausgeführt werden muss (setzen Sie diese erneut ein ~/.zshrc):

svn mv {^,}2010

Die erste Klammererweiterung kommt ins Spiel, was dazu führt svn mv ^2010 2010. Dann wird das Muster ^2010(eine Verknüpfung für "Dateien übereinstimmen, *aber nicht 2010") erweitert.

Wenn Sie ein .svnVerzeichnis haben, müssen Sie es vom Umzug ausschließen. Dies ist standardmäßig in Ordnung, da .svnes nicht mit übereinstimmt *(es ist eine Punktdatei). Es gibt jedoch Komplikationen:

  • Wenn Sie die glob_dotsOption festgelegt haben, müssen Sie auch Folgendes ausschließen .svn:

    svn mv !(2010|.svn) 2010             # requires setopt ksh_glob
    svn mv *~(.svn|2010) 2010            # requires setopt extended_glob
  • Wenn Sie Punktdateien haben und diese nicht festgelegt haben glob_dots, müssen Sie sie separat verschieben:

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

    Um es auf einmal zu tun:

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

Eine andere Möglichkeit, die in diesem Fall in zsh funktioniert (wenn Sie keine Unterverzeichnisse haben), besteht darin svn mv *(.D) 2010, nur reguläre Dateien ( .) einschließlich Punktdateien ( D) abzugleichen .

Gilles 'SO - hör auf böse zu sein'
quelle
3

ZSH hat einen hilfreichen Glob-Operator, der alles außer einem Vornamen abgleichen kann ^. Das würde also funktionieren (aber es ist ZSH-spezifisch und Sie müssen es setopt extendedglobzuerst tun ):

$ svn mv ^2010 2010
Michael Mrozek
quelle
Ich kenne die !()Syntax, mit der funktioniert zsh. Wie unterscheidet sich die ^Syntax? In meiner Shell funktioniert es nicht. Welche Option müsste ich einstellen, um es zu aktivieren?
Caleb
@Caleb Entschuldigung, ich dachte, es ist standardmäßig aktiviert, aber anscheinend müssen Sie setopt extendedglob. Ich wusste es nicht !(), es klingt nach einer eher Cross-Shell-Methode
Michael Mrozek
svn mv {^,}2010um zu vermeiden, dass der Verzeichnisname zweimal
eingegeben wird
0

Wenn Ihre Dateien "zahme" Namen haben (kein Leerzeichen, nicht druckbare Zeichen oder \[?*):

svn mv $(ls | grep -vx 2010) 2010
Chris Ting
quelle
2
Dateien können nicht als "zahm" bezeichnet werden. Ever :) Die für bash und zsh vorgestellten Shell-Glob-Lösungen umgehen dieses Problem.
Caleb