Bagaimana cara memindahkan semua file dari direktori saat ini ke direktori atas?

133

Bagaimana cara memindahkan semua file dari direktori saat ini ke direktori teratas di linux?

Saya mencoba sesuatu seperti mv *.*, tetapi tidak berhasil.

Jens Erat
sumber
Saya tidak punya cukup perwakilan untuk mengulang pertanyaan, tetapi bolehkah saya menyarankan [linux] [mv] [cwd] [files], atau yang serupa?
Stephan202
Saya telah mengulang pertanyaan ini sesuai permintaan Stephan202.
sebelas81

Jawaban:

202

Perintah yang Anda cari adalah

mv * .[^.]* ..

atau (lihat di bawah untuk info lebih lanjut):

(shopt -s dotglob; mv -- * ..)

Penjelasan: mvperintah memindahkan file dan direktori. Argumen terakhir mvadalah target (dalam hal ini direktori satu langkah "naik" di pohon, ..). Argumen sebelum itu adalah file sumber dan direktori. Tanda bintang ( *) adalah wildcard yang cocok dengan semua file yang tidak dimulai dengan titik. File yang dimulai dengan titik (dotfiles) "disembunyikan". Mereka dicocokkan menggunakan pola .[^.]*(lihat edit di bawah).

Lihat halaman yang saya tautkan untuk informasi lebih lanjut tentang mv.


Kenapa .[^.]*bukannya .*?

Seperti yang ditunjukkan dengan benar oleh Chris Johnsen : polanya .*juga cocok .dan ... Karena Anda tidak ingin (dan tidak bisa) memindahkannya, lebih baik menggunakan pola yang cocok dengan nama file apa pun yang dimulai dengan titik kecuali keduanya . Pola .[^.]*tidak hanya itu: cocok dengan nama file (1) dimulai dengan titik (2) diikuti oleh karakter yang bukan titik (3) diikuti oleh nol atau lebih karakter sewenang-wenang.

Sebagai Paggas menunjukkan , kami juga harus menambahkan pola .??*untuk mencocokkan file yang dimulai dengan dua titik. Lihat jawabannya untuk solusi alternatif menggunakan find.

Jawaban Arjan menyebutkan shoptuntuk menghindari semua masalah dengan dotfile. Tapi kemudian masih ada masalah dengan file yang dimulai dengan tanda hubung. Dan itu membutuhkan tiga perintah. Tetap saja, saya suka ide itu. Saya mengusulkan untuk menggunakannya seperti ini:

(shopt -s dotglob; mv -- * ..)

Ini dijalankan shoptdalam subshell (sehingga tidak perlu panggilan kedua shopt) dan menggunakan --sehingga file yang dimulai dengan tanda hubung tidak akan ditafsirkan sebagai argumen mv.

Stephan202
sumber
7
Menggunakan .*mungkin menyebabkan mv menghasilkan peringatan / kesalahan tentang tidak bisa bergerak .dan ... Anda mungkin mencoba mv * .[^.]* ..sebagai gantinya.
Chris Johnsen
1
@alain: sama-sama, dan selamat datang di situs ini! (Jika (dan hanya jika) salah satu posting di sini cukup menjawab pertanyaan Anda, maka Anda dapat menandainya seperti itu. Itu akan mendapatkan poster 15 poin reputasi ekstra, dan juga memberi Anda 2 rep ekstra.)
Stephan202
Aku benar-benar seperti solusi shopt berjalan di subkulit :)
Paggas
2
Tidak ada salahnya dalam sintaks *. * - termasuk .. hanya berbahaya bila digunakan dengan chmod dan chown dan flag "recurse", yaitu chmod -R atau chown -R. Dan dalam kasus tersebut, jangan pernah mengetik chown. * Atau chmod. * - chown direktori teratas di jalur yang Anda cari dan gunakan -h (jangan ikuti tautan simbolis). Tapi, mv .. tidak melakukan apa-apa jadi jangan khawatir.
chris
1
Tiga pola yang benar adalah *, .[^.]*dan ..?*. Yang kedua mungkin .[!.]*untuk shell yang lebih lama (POSIX). Baca juga
42

Jawaban singkat: gunakan

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Jawaban panjang:

Perintah

mv * .* ..

tidak akan berfungsi karena .*dapat mencocokkan .dan ... Tapi perintahnya

mv * .[^.]* ..

juga tidak akan berfungsi, karena .[^.]*tidak akan cocok, misalnya ..filename,! Sebaliknya, yang saya lakukan adalah

mv * .[^.] .??* ..

yang akan cocok dengan semuanya kecuali .dan ... *akan cocok dengan semua yang tidak dimulai dengan a ., .[^.]akan cocok dengan semua nama file 2 karakter yang dimulai dengan titik kecuali .., dan .??*akan cocok dengan semua nama file yang dimulai dengan titik dengan setidaknya 3 karakter.

Lebih baik lagi, Anda bisa menggunakannya

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

yang menghindari gumpalan jelek di mv * .[^.] .??* ..!

Pagga
sumber
1
Juga, saya lupa mencatat pentingnya - sehingga perintah itu bekerja dengan benar dengan nama file yang dimulai dengan tanda hubung. Saya telah memasukkan - dalam menemukan jawaban saya. Jawaban yang lebih lengkap menggunakan gumpalan adalah "mv - *. [^.]. ?? * ..".
Paggas
+1: Saya kembali untuk menambahkan ..?*komentar saya, dan Anda sudah menanganinya.
Chris Johnsen
1
Apa yang mungkin salah dengan mencoba mv ..? Itu tidak melakukan apa-apa dan tidak bisa melakukan apa-apa. Ada perintah lain di mana ia dapat melakukan sesuatu (chmod dan chown) tetapi mv dan rm tidak melakukan apa-apa. atau ..
chris
1
Ini memberikan mv: opsi ilegal - t
pal4life
1
Bono, tanda hubung ganda memberitahu mvuntuk berhenti mencari opsi perintah lebih lanjut. Kawat gigi adalah nama file yang dihasilkan. Tanda plus mengatakan alih-alih menjalankan exec per hasil (mis. Per nama file), letakkan sebanyak mungkin hasil dalam satu exec sebanyak mungkin. Untuk kelengkapannya, -t..katakan memindahkan tujuan tujuan untuk memindahkan semua file-file ini.
Isuldor
14

Hanya demi kelengkapan, Anda juga dapat memberi tahu Bash shell untuk memasukkan file tersembunyi, menggunakan shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob
Arjan
sumber
+1. Jauh lebih bersih. Saya pikir ada sedikit perbaikan. Lihat pembaruan untuk jawaban saya.
Stephan202
8

Mv tidak memiliki fungsionalitas memindahkan file tersembunyi saat menggunakan *- jadi mengapa tidak menggunakan salin saja?

cp -rf . ..

rm -rf *

Tidak perlu masuk ke solusi kompleks dotglobbing dan menggunakan perintah find.

Micky Martin
sumber
Peringatan Jika Anda bergerak di sistem file yang sama , di bagian terbesar dari kasus Anda tidak benar-benar menyalin file tetapi hanya memperbarui entri direktori tanpa memindahkan inode atau file contenents. Lihat genap [1 ]. Dengan cpdan rmsebaliknya Anda benar-benar menyalin semua.
Hastur
6
rsync -a --remove-source-files . ..

rsync adalah alat penyalinan file yang sangat kuat, umumnya digunakan untuk melakukan backup dan mirror jarak jauh inkremental yang efisien.

Dengan perintah di atas, kami menyuruh rsyncmenyalin konten .ke..

Switch -amemungkinkan rekursi menjadi .subdirektori dan memungkinkan beberapa opsi umum lainnya.

Switch --remove-source-filesmemberitahu rsync untuk menghapus file sumber setelah salinan berhasil, yaitu itu membuat rsync berperilaku serupa dengan mvperintah.

mrucci
sumber
1
Penjelasan lebih sedikit akan menyenangkan.
ChrisF
Tentu, harap ini lebih jelas sekarang.
mrucci
Catatan yang --remove-source-filestidak akan menghapus direktori (disinkronkan).
Dennis
Bagus, solusi yang diterima memberi saya -bash: /bin/mv: Argument list too longkesalahan. Yang ini berfungsi seperti pesona.
userlond
2

Pada akhirnya mencoba mv .akan gagal karena mv tidak akan dapat memutuskan tautan direktori yang sedang Anda mv * ..masuki. Anda dapat memindahkan file di cwd.

DaveParillo
sumber
2
mv * .??* ../.

*mendapat semua file bukan-titik. .??*dapatkan semuanya. file setidaknya tiga byte, yang berfungsi untuk semua yang sah. Sesuatu yang tersisa Anda mungkin ingin rmbukan mvpula.

Itu ../.tidak menawarkan manfaat langsung ..tetapi ketika melakukan pindah-ke-direktori itu adalah kebiasaan yang sangat baik untuk masuk, karena akan gagal, seperti yang Anda inginkan, jika ada sesuatu yang salah dengan jalan. Misalnya, di mv xyz bletchmana Anda pikir bletch adalah direktori, dapat dibuat lebih pasti mv xyz bletch/..

DigitalRoss
sumber
2
Anda mungkin menambahkan .[^.]untuk mendapatkan file sampul seperti .a.
Chris Johnsen
Tidak ada perbedaan antara ../ dan ../. jadi saya tidak akan repot mengetik. setelah tebasan. Juga, dalam kasus mv dan rm, tidak ada salahnya untuk disertakan. dan .. dalam daftar, yaitu tidak ada sesuatu yang menakutkan atau salah dengan mv *. * / path / to / file /, sama seperti rm. atau bahkan -rf. tidak melakukan apa-apa.
chris
2

Perintah yang diperkecil ini berfungsi pada sebagian besar shell modern:

\mv -- {,.{[^.],??}}* ..

Jika tidak disebutkan adalah solusi portabel:

\mv -- * .[^.] .??* ..

Fitur:

  1. \ Mencegah alias mengubah mv yang tidak diinginkan.

  2. - Mencegah nama file yang mengandung tanda hubung (-xyz) dari ditafsirkan sebagai argumen baris perintah.

  3. . [^.] cocok dengan semua nama file dua karakter yang diawali dengan. kecuali ..

  4. . ?? * cocok dengan semua nama file lainnya, tiga karakter atau lebih lama.

Implementasi Naif:

  1. Melewati berikut ini menyembunyikan nama file UNIX, yang diawali dengan. (.bashrc).

    mv * ..
    
  2. Pencocokan berikut .. yang secara rekursif mencoba untuk memindahkan setiap direktori pada akhirnya semua jalan kembali ke / ke .. direktori kerja saat ini ($ PWD atau pwd). Jangan pernah gunakan.

    mv .* ..
    
dhchdhd
sumber
2

Lebih tepat menggunakan pola * .[!.] .??*daripada * .[^.] .??*karena yang pertama juga akan bekerja dengan cangkang yang lebih lama seperti ksh88:

mv -- * .[!.] .??* ..
  • -- mencegah masalah ketika Anda memiliki nama file yang dimulai dengan -
  • * cocok dengan semua nama file yang tidak dimulai dengan a .
  • tidak ada nama file satu karakter yang dimulai dengan .yang Anda dapat / harus pindah
  • .[!.] cocok dengan kedua nama file karakter yang dimulai dengan a .
  • .??* cocok dengan ketiga nama file karakter (atau lebih panjang) yang dimulai dengan a .

Dengan ksh88, pola nama file .[^.]sebenarnya akan cocok dengan nama file ..(yang selalu ada) dan .^(yang mungkin tidak ada), memiliki efek yang berlawanan dengan apa yang diinginkan.

jrw32982
sumber
0

Temukan dan dapatkan pekerjaan juga. Struktur semacam ini mungkin berguna jika Anda ingin memilih file pada kriteria yang lebih rumit dengan memodifikasi find dan egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..
pengguna3192145
sumber
0

Saya pikir solusi termudah untuk memindahkan semua file ke dir induknya. akan menjadi

mv "`ls`" ../

atau, Jika ada file / direktori tersembunyi

menggunakan:

mv "`ls -a`" ../ 2>/dev/null

Juga, katakanlah Anda ingin memindahkan konten beberapa folder ke salah satu folder internal tony (katakanlah)

menggunakan:

mv "`ls -a`" /tony 2>/dev/null

catatan:

"`ls -a`" 

Untuk memindahkan file yang memiliki spasi di dalamnya.

2>/dev/null

Apakah untuk menekan peringatan / error karena ls -aakan mencetak .dan ..folder juga dan Anda tidak dapat memindahkan atau menyalinnya. Jadi untuk folder-folder itu akan muncul kesalahan (jika kita tidak menggunakan 2> / dev / null) bahwa itu tidak dapat memindahkan mereka dan sisanya akan dipindahkan dengan nyaman.

Terbaik untuk menghindari ls -ajika tidak ada file tersembunyi dan cukup gunakan ls.

Prabhat Kumar Singh
sumber
Sudahkah Anda mencoba apa yang akan terjadi ketika Anda berlari mv $(ls -a)? Itu akan mengetuk direktori saat ini dan direktori di bawahnya, karena ls -aakan menampilkan ..juga.
Sami Laine
Terima kasih, @SamiLaine untuk saran saya telah melakukan koreksi. Tetapi mv ls -a ../akan juga bekerja sesuai kebutuhan, Ya itu akan menunjukkan kesalahan-kesalahan seperti yang saya sebutkan di atas tetapi selain itu akan memindahkan folder / file yang diperlukan ke dir induk.
Prabhat Kumar Singh
Ini tidak akan berfungsi untuk file dengan spasi.
kenorb
@kenorb, Anda perlu menggandakan kutipan lsperintah untuk memindahkan file dengan spasi. Saya telah melakukan perubahan yang diperlukan. Terima kasih telah menunjukkan.
Prabhat Kumar Singh