«Mkdir Foo; svn mv * foo ”

9

Я часто хочу сделать несколько вариантов этой идиомы:

$ mkdir 2010
$ svn mv * 2010

Конечно, я получаю ошибку, потому что глобус также соответствует 2010:

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

Есть ли способ заменить "svn mv * 2010"на другой однострочник, который делает правильную вещь?

Лорин Хохштайн
источник
Это не вопрос, специфичный для SVN, это относится и к ванили mv. Тем не менее, с mv, mv * newdirу меня работает, правда , с ошибкой.
crazy2be

Ответы:

14

Под ksh, bash или zsh:

svn mv !(2010) 2010

Под Bash, вам нужно запустить в shopt -s extglobпервую очередь (положить его в свой ~/.bashrc). Под zsh вам нужно setopt -o ksh_globсначала запустить (поместите в свой ~/.zshrc).

Это не перемещает точечные файлы (файлы, чье имя начинается с .). Если у вас есть, переместите их отдельно. Будьте осторожны, чтобы исключить .svnкаталог, если он у вас есть. В кш или зш:

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).

Жиль "ТАК - перестань быть злым"
источник
3

ЗШ имеет полезный оператор Глобы , чтобы соответствовать все , кроме заданного имени ^. Так что это будет работать (но это специфично для ZSH, и вам нужно setopt extendedglobсначала):

$ svn mv ^2010 2010
Михаил Мрозек
источник
Я знал о !()синтаксисе, который работает с zsh. Чем отличается ^синтаксис? Это не работает в моей оболочке, какой параметр мне нужно установить, чтобы включить его?
Калеб
@Caleb Извините, я думал, что он включен по умолчанию, но, видимо, вам нужно setopt extendedglob. Я не знал о !(), это звучит как более перекрестный способ сделать это
Майкл Мрозек
svn mv {^,}2010чтобы не вводить имя каталога дважды
Жиль "ТАК - перестань быть злым"
0

Если ваши файлы имеют «ручные» имена (без пробелов, непечатных символов или \[?*):

svn mv $(ls | grep -vx 2010) 2010
Крис Тинг
источник
2
Нельзя доверять файлам иметь «ручные» имена. Когда-либо :) Решения оболочки, представленные для bash и zsh, аккуратно обходят эту проблему.
Калеб