“Mkdir foo; svn mv * foo ”

9

Saya sering ingin melakukan beberapa varian dari ungkapan ini:

$ mkdir 2010
$ svn mv * 2010

Tentu saja, saya mendapatkan kesalahan karena glob juga cocok dengan 2010:

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

Apakah ada cara untuk mengganti "svn mv * 2010"dengan liner yang berbeda yang melakukan hal yang benar?

Lorin Hochstein
sumber
Ini bukan pertanyaan khusus untuk svn, ini berlaku untuk vanila mvjuga. Namun, dengan mv, mv * newdirbekerja untuk saya, meskipun dengan kesalahan.
crazy2be

Jawaban:

14

Di bawah ksh, bash, atau zsh:

svn mv !(2010) 2010

Di bawah bash, Anda harus menjalankannya shopt -s extglobdulu (letakkan di Anda ~/.bashrc). Di bawah zsh, Anda harus menjalankannya setopt -o ksh_globdulu (letakkan di Anda ~/.zshrc).

Ini tidak memindahkan file dot (file yang namanya dimulai dengan .). Jika Anda memiliki beberapa, pindahkan secara terpisah. Berhati-hatilah untuk mengecualikan .svndirektori jika Anda memilikinya. Dalam ksh atau zsh:

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

Dalam bash, ini lebih rumit karena Anda juga perlu mengecualikan .dan ...

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

Zsh juga memiliki sintaks yang berbeda dan lebih pendek, yang mengharuskan berjalan setopt -o extended_globterlebih dahulu (sekali lagi, masukkan ini ~/.zshrc):

svn mv {^,}2010

Ekspansi brace pertama ikut berperan, menghasilkan svn mv ^2010 2010. Kemudian pola ^2010(jalan pintas untuk "file yang cocok *tetapi tidak 2010") diperluas.

Jika Anda memiliki .svndirektori, Anda harus mengeluarkannya dari pemindahan. Ini ok secara default, karena .svntidak cocok dengan *(ini file dot). Namun, ada beberapa komplikasi:

  • Jika Anda telah mengatur glob_dotsopsi, Anda harus mengecualikan .svnjuga:

    svn mv !(2010|.svn) 2010             # requires setopt ksh_glob
    svn mv *~(.svn|2010) 2010            # requires setopt extended_glob
  • Jika Anda memiliki file dot dan belum Anda atur glob_dots, Anda harus memindahkannya secara terpisah:

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

    Untuk melakukannya dalam sekali jalan:

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

Cara lain yang akan bekerja di zsh dalam kasus ini (jika Anda tidak memiliki subdirektori) adalah svn mv *(.D) 2010, untuk mencocokkan hanya file biasa ( .) termasuk file dot ( D).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

ZSH memiliki operator glob yang membantu mencocokkan semuanya kecuali nama yang diberikan ^,. Jadi ini akan berhasil (tapi khusus ZSH, dan Anda harus setopt extendedglobterlebih dahulu):

$ svn mv ^2010 2010
Michael Mrozek
sumber
Saya sudah tahu tentang !()sintaks yang berfungsi zsh. Apa ^perbedaan antara sintaksis? Ini tidak berfungsi di shell saya, opsi apa yang harus saya atur untuk mengaktifkannya?
Caleb
@ Caleb Maaf, saya pikir itu diaktifkan secara default, tetapi tampaknya Anda perlu setopt extendedglob. Saya tidak tahu !(), sepertinya cara yang lebih mudah untuk melakukannya
Michael Mrozek
svn mv {^,}2010untuk menghindari mengetik nama direktori dua kali
Gilles 'SO- stop being evil'
0

Jika file Anda memiliki nama "jinak" (tanpa spasi, karakter yang tidak diinginkan atau \[?*):

svn mv $(ls | grep -vx 2010) 2010
Chris Ting
sumber
2
File tidak dapat dipercaya memiliki nama "jinak". Selalu :) Solusi glob shell disajikan untuk bash dan zsh dengan rapi menghindari masalah ini.
Caleb