Cara memindahkan semua file termasuk file tersembunyi ke direktori induk melalui *

113

Ini pasti pertanyaan yang populer tetapi saya tidak dapat menemukan jawabannya.

Cara memindahkan semua file melalui * termasuk file tersembunyi juga ke direktori induk seperti ini:

mv /path/subfolder/* /path/

Ini akan memindahkan semua file ke direktori induk seperti yang diharapkan tetapi tidak akan memindahkan file tersembunyi. Bagaimana cara melakukannya?

TroodoN-Mike
sumber
1
pertanyaan ini memiliki duplikat di SU , dengan jawaban yang lebih benar (meskipun bukan yang diterima): cp -r /path/to/source/. /destination
Florian

Jawaban:

202

Anda dapat menemukan serangkaian solusi lengkap tentang ini di jawaban UNIX & Linux untuk Bagaimana Anda memindahkan semua file (termasuk yang tersembunyi) dari satu direktori ke direktori lain? . Ini menunjukkan solusi dalam Bash, zsh, ksh93, standar (POSIX) sh, dll.


Anda dapat menggunakan dua perintah ini secara bersamaan:

mv /path/subfolder/* /path/   # your current approach
mv /path/subfolder/.* /path/  # this one for hidden files

Atau semuanya ( terima kasih pfnuesel ):

mv /path/subfolder/{.,}* /path/

Yang berkembang menjadi:

mv /path/subfolder/* /path/subfolder/.* /path/

(contoh: echo a{.,}bmeluas ke a.b ab)

Perhatikan ini akan menampilkan beberapa peringatan:

mv: cannot move ‘/path/subfolder/.’ to /path/.’: Device or resource busy
mv: cannot remove /path/subfolder/..’: Is a directory

Abaikan saja: ini terjadi karena /path/subfolder/{.,}*juga meluas ke /path/subfolder/.dan /path/subfolder/.., yang merupakan direktori dan direktori induk (Lihat Apa artinya "." Dan ".." saat berada dalam folder? ).


Jika Anda hanya ingin menyalin, Anda dapat menggunakan:

cp -r /path/subfolder/. /path/
#                     ^
#                     note the dot!

Ini akan menyalin semua file, baik yang normal maupun yang tersembunyi, karena /path/subfolder/.diperluas ke "semuanya dari direktori ini" (Sumber: Bagaimana cara menyalin dengan cp untuk memasukkan file tersembunyi dan direktori tersembunyi beserta isinya? )

fedorqui 'JADI berhenti merugikan'
sumber
2
Kawat gigi hanyalah jalan pintas mv /path/subfolder/* /path/subfolder/.* /path/, tidak benar-benar diperlukan untuk menggabungkan dua perintah menjadi satu.
chepner
7
Saya mendapatkan kesalahan berikut:mv: overwrite `/path/.'? y mv: cannot move `/path/subfolder/.' to `/path/.': Device or resource busy mv: overwrite `/path/..'? y mv: cannot move `/path/subfolder/..' to `/path/..': Device or resource busy
Dejan
@Dejan Abaikan saja. .menunjukkan direktori saat ini dan ..menunjukkan updirektori. Anda pasti telah memperhatikan bahwa semua file lainnya dipindahkan.
Debiprasad
Perlu disebutkan bahwa pintasan kawat gigi tidak akan berfungsi untuk semua cangkang, tetapi perintah @chepner menurut saya akan
Jesús Carrera
7
"Abaikan saja peringatannya" mungkin tidak selalu merupakan ide yang bagus. Saat ini saya mengalami masalah dengan skrip yang mengharuskan saya menghentikan eksekusi jika ada langkah yang gagal - karena solusi ini selalu menyebabkan kesalahan, maka skrip saya akan mati. Saya perlu cara untuk menentukan apakah perintah mv gagal atau tidak ...
MarioVilas
29

Saya pikir ini yang paling elegan, karena juga tidak mencoba bergerak ..:

mv /source/path/{.[!.],}* /destination/path
Vanderstaaij
sumber
1
ya saya perhatikan itu memberikan pesan kesalahan itu juga, bagus ditemukan.
Joseph Astrahan
Saya pikir ini adalah solusi yang sangat baik tetapi agak sulit untuk mengingat pola itu
Dylan B
ini akan kehilangan file seperti ..anythingatau ...anythingdll. - stackoverflow.com/a/31438355/2351568 berisi regex yang benar untuk masalah ini. || tetapi bagaimanapun juga menggunakan shopt -s dotglobmasih merupakan solusi yang lebih baik!
DJCrashdummy
@DylanB jangan menghafalnya. ingat bahwa itu cocok dengan apa pun yang ada di kurung kurawal, dipisahkan dengan koma. {a,b}*akan menemukan semua file yang dimulai dengan a atau b seperti "anatomi" dan "bulldozer". Pertandingan kedua hanyalah pertandingan kosong, setara dengan *, dan pertandingan pertama setara dengan .[!.], di mana grup [!.]berarti grup TIDAK dimulai dengan a .. Artinya, .*tetapi tidak ..*.
mazunki
28

Ini akan memindahkan semua file ke direktori induk seperti yang diharapkan tetapi tidak akan memindahkan file tersembunyi. Bagaimana cara melakukannya?

Anda bisa menyalakan dotglob:

shopt -s dotglob               # This would cause mv below to match hidden files
mv /path/subfolder/* /path/

Untuk mematikan dotglob, Anda perlu mengatakan:

shopt -u dotglob
devnull
sumber
Sangat membantu. Ingin mengetahui lebih lanjut tetapi shopt adalah bawaan sehingga man shopttidak berfungsi dan help shoptsangat singkat. Tapi Anda bisa melakukannya bashman () { man bash | less -p "^ $1 "; }dan kemudian bashman shoptmembaca semua tentang itu dengan lugas. (Mungkin harus menekan n untuk melompat ke bawah ke perintah jika ada baris yang dimulai dengan shopt, seperti yang saya temukan.)
Nick Rice
2
ini juga akan mempengaruhi semua perintah lain seperti ls.. jadi bukan yang Anda inginkan, mungkin
phil294
5

Solusi alternatif yang lebih sederhana adalah dengan menggunakan rsyncutilitas:

sudo rsync -vuar --delete-after --dry-run path/subfolder/ path/

Catatan: Perintah di atas akan menunjukkan apa yang akan diubah. Untuk menjalankan perubahan aktual, hapus--dry-run .

Keuntungannya adalah folder asli ( subfolder) akan dihapus serta bagian dari perintah, dan saat menggunakan mvcontoh di sini Anda masih perlu membersihkan folder Anda, belum lagi sakit kepala tambahan untuk menutupi file yang tersembunyi dan tidak tersembunyi dalam satu tempat. pola.

Selain itu rsyncmemberikan dukungan untuk menyalin / memindahkan file antara remote dan itu akan memastikan bahwa file disalin persis seperti aslinya ( -a).

-uParameter yang digunakan akan melewatkan file baru yang ada, -rmasuk kembali ke direktori dan -vakan meningkatkan verbositas.

kenorb
sumber
Solusi terbaik yang pernah ada! Dalam kasus saya, saya baru saja menghapus parameter -u, karena saya tidak ingin memperbarui folder root. Terima kasih
Thales Ceolin
Ini adalah salah satu perintah di mana jika Anda tidak berhati-hati, Anda benar-benar dapat mengacaukan segalanya di linux, secara permanen. Harap perbarui jawaban Anda untuk menyertakan sudo sebelum perintah rsync, jika tidak, pengguna dapat dengan mudah mendapatkan Izin Ditolak untuk mkdir, tetapi penghapusan file akan terus berlanjut, dengan demikian, perintah rsync akan menghapus seluruh direktori yang ingin Anda pindahkan, dan tidak melakukan apa pun . Anda akan kehilangan seluruh direktori Anda. Setelah Anda menambahkan sudo ke jawaban Anda, ini mungkin jawaban yang diterima. Jadi perintahnya adalah: sudo rsync -vuar --delete-after path / subfolder / path /
Blue Water
@JohnnyB Maaf tentang ketidaknyamanan ini. Saya telah menambahkan sudodan --dry-run, sehingga orang dapat menguji perubahan sebelum menjalankan perintah sebenarnya untuk menghindari potensi kekacauan.
kenorb
Oh, saya tidak menyadari ada opsi --dry-run. Tambahan yang bagus. Tidak perlu permintaan maaf. Ini luar biasa.
Blue Water
3

Izinkan saya memperkenalkan Anda kepada teman saya "dotglob". Ini menyala dan mati apakah "*" termasuk file tersembunyi atau tidak.

$ mkdir test
$ cd test
$ touch a b c .hidden .hi .den
$ ls -a
. ..  .den  .hi .hidden a b c

$ shopt -u dotglob
$ ls *
a b c
$ for i in * ; do echo I found: $i ; done
I found: a
I found: b
I found: c

$ shopt -s dotglob
$ ls *
.den  .hi .hidden a b c
$ for i in * ; do echo I found: $i ; done
I found: .den
I found: .hi
I found: .hidden
I found: a
I found: b
I found: c

Defaultnya adalah "off".

$ shopt dotglob
dotglob         off

Yang terbaik adalah menyalakannya kembali ketika Anda selesai jika tidak, Anda akan membingungkan hal-hal yang menganggapnya akan mati.

TomOnTime
sumber
3

Dengan menggunakan findperintah yang berhubungan dengan mvperintah, Anda dapat mencegah mvperintah untuk mencoba memindahkan direktori (misalnya ..dan .) dan subdirektori. Inilah salah satu opsinya:

find /path/subfolder -maxdepth 1 -type f -name '*' -exec mv -n {} /path \;

Ada masalah dengan beberapa jawaban lain yang diberikan. Misalnya, setiap hal berikut akan mencoba memindahkan subdirektori dari jalur sumber:

1) mv /path/subfolder/* /path/ ; mv /path/subfolder/.* /path/
2) mv /path/subfolder/{.,}* /path/ 
3) mv /source/path/{.[!.],}* /destination/path

Juga, 2) termasuk file. dan .. file dan 3) melewatkan file seperti ..foobar, ... barfoo, dll.

Anda dapat menggunakan,, mv /source/path/{.[!.],..?,}* /destination/pathyang akan menyertakan file yang terlewat oleh 3), tetapi masih akan mencoba untuk memindahkan subdirektori. Menggunakan findperintah dengan mvperintah seperti yang saya jelaskan di atas menghilangkan semua masalah ini.

teancum144
sumber
2

Solusi saya untuk masalah ini ketika saya harus menyalin semua file (termasuk .file) ke direktori target yang mempertahankan izin adalah: (timpa jika sudah ada)

yes | cp -rvp /source/directory /destination/directory/

yesadalah untuk secara otomatis menimpa file tujuan, rrekursif, vverbose, p mempertahankan izin.

Perhatikan bahwa jalur sumber tidak diakhiri dengan a/ (jadi semua file / direktori dan. File disalin)

Direktori tujuan diakhiri dengan/ saat kita menempatkan konten folder sumber ke tujuan secara keseluruhan.

Rajneesh Gadge
sumber
Sementara itu yesadalah perintah yang luar biasa untuk digunakan jika Anda ingin mengganti file tujuan, itu tidak selalu diinginkan. Gunakan hanya jika Anda yakin ingin melakukan ini. Juga, apakah ada perbedaan antara yes | cp ...dan cp -f ...?
mazunki