Bagaimana cara menyalin file dan subdirektori tersembunyi (dimulai dengan titik) di linux?

10

Bagaimana cara menyalin file tersembunyi dan subdirektori tersembunyi (yang dimulai dengan titik) di folder A ke folder B? Sebagai contoh jika saya memiliki struktur ini:

A/a
A/b
A/.a
A/.b/
A/.b/somefile
A/.b/.c

Saya ingin menyalin ke B hanya file yang tersembunyi dan subdirektori tersembunyi di A:

B/.a
B/.b/
B/.b/somefile
B/.b/.c

Saya sudah mencoba perintah ini: cp A/.* Bdari pertanyaan pengguna super ini . Namun, itu tidak menyalin subdirektori. Juga mencoba cp -r A/.* B, tetapi salinan .jadi saya akhiri dengan salinan tepat A (termasuk file normal). Bantuan apa pun dihargai.

gaboroncancio
sumber

Jawaban:

16

Misalnya Anda hanya mencari file dan folder tersembunyi di level A dan tidak mau, misalnya

A/b/.hidden

untuk disalin, Anda harus dapat menggunakan ini:

cp -r A/.[^.]* B

Ini pada dasarnya berarti menyalin apa pun yang dimulai dengan a .dan kemudian karakter apa pun selain .Itu yang menyaring .dan..

Sunting: Menghapus -p dari perintah cp karena Penanya belum mengindikasikan dia ingin mempertahankan kepemilikan, tanggal, dll.

Kemahahadiran
sumber
Ini berfungsi untuk nama file dan direktori contoh yang diberikan dalam pertanyaan, tetapi teks dari pertanyaan mengatakan "file tersembunyi dan subdirektori tersembunyi (yang dimulai dengan titik)", dan jawaban ini tidak akan menemukan file dan direktori yang namanya dimulai dengan dua titik; misalnya ..c,.
Scott
Itu adalah kasus tepi, tetapi kekhawatiran yang sah tidak kurang. Saya tidak mempertimbangkan itu. Anda dapat menjelaskannya dengan beralih ke .*[^.]tetapi kemudian Anda akan kehilangan file yang diakhiri dengan .. Saya pikir Anda memang perlu globbing diperpanjang untuk benar-benar menjelaskan semua kasus.
Omnipresence
4

Masalah dengan A/.*adalah bahwa ada direktori .di Amana juga cocok pola.

Anda dapat mengaktifkan pola gumpal diperpanjang dan menggunakan yang berikut:

shopt -s extglob
cp -r A/.!(?(.)) B    

Ini cocok dengan file yang namanya dimulai dengan titik dan karakter kedua yang bukan titik atau tidak sama sekali (? (.) Tidak cocok dengan titik,! (...) meniadakannya, yaitu! (? (.)) Cocok dengan yang lainnya daripada tidak sama sekali atau titik).

choroba
sumber
+1 untuk jawaban yang benar. Perhatikan bahwa .!(@(|.))(AFAICT) sama dengan di atas, (IMNSHO) sedikit lebih jelas, dan hanya satu karakter yang lebih panjang.
Scott
3

Untuk kasus seperti ini akan merekomendasikan menggunakan finddaripada cpseperti ini:

find A/ -type f -maxdepth 1 -name '.*' -exec cp -p {} B/ \;

Sintaks dasarnya rusak seperti ini:

  • find A/ -type f: finditem dalam direktori A/yang tipenya adalah file (bukan direktori) ...
  • -maxdepth 1 -name '.*': Untuk ini untuk satu maxdepthdari 1 direktori dan yang namedimulai dengan ..
  • -exec cp -p {} B/ \;: Dan sekali file-file ini ditemukan, execyang cpperintah dengan -pbendera untuk melestarikan tanggal / waktu dari sumber ( {}) ke tujuan B/.

Saya suka menggunakan maxdepthuntuk menambahkan lapisan kontrol jadi saya tidak sengaja menyalin seluruh sistem file. Tapi jangan ragu untuk menghapusnya.

JakeGould
sumber
0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d menyediakan daftar rekursif dalam A dengan hanya direktori
  • grep -E "\." memfilter direktori dengan titik (yaitu: direktori tersembunyi)
  • opsi -E diperlukan di sini karena tanpa itu berarti "direktori saat ini" juga
  • backslash adalah untuk menghindari makna, di bawah regexp, dari "karakter apa saja"
  • cp -r untuk menyalin secara rekursif

Saya telah membuat struktur file dan folder untuk A dan menjalankan perintah di Git Bash (Saya tidak menggunakan linux sekarang) dan berhasil.

malarres
sumber
Ini pecah jika file memiliki spasi atau karakter khusus di nama atau jalurnya.
slhck
Terima kasih telah memperhatikan :) Sebenarnya saya dibatasi pada "test case" oleh @gaboroncancio. Jika Anda dapat memberi saya baterai tes lain, saya dapat mencoba meningkatkannya (tentu saja jika Anda mau, memperbaikinya sendiri dengan mengedit respons ini atau membuat jawaban baru)
malarres
Anda cukup menaruh dotfiles di folder bernama A B, dan kemudian akan bertindak secara tak terduga karena akan berkembang menjadi cp -r A B/.dotfile B. Saran umum adalah jangan menguraikan findatau lsmenghasilkan sama sekali. Jika Anda menggunakan, findAnda juga harus menggunakan opsi sendiri untuk memfilter daripada grep, dan jika Anda mem-pipe findoutput di tempat lain, gunakan -print0, atau langsung panggil perintah yang Anda inginkan. Lihat find manualnya .
slhck
Bahkan lebih umum, ketika bekerja dengan file itu paling aman untuk menggunakan gumpalan shell seperti yang dijelaskan dalam jawaban lain (meskipun mereka sering perlu extglobdiatur).
slhck
Terima kasih untuk tautannya. Mari kita tinggalkan findparsing itu.
malarres
0

Sebagai alternatif, Anda dapat menggunakan perintah lain ini jika karakter kedua adalah alfanumerik ( sumber ):

cp -r A/.[a-zA-Z0-9]* B
gaboroncancio
sumber
Ini berfungsi untuk nama file dan direktori contoh yang diberikan dalam pertanyaan, tetapi teks dari pertanyaan mengatakan "file tersembunyi dan subdirektori tersembunyi (yang dimulai dengan titik)", dan jawaban ini tidak akan menemukan file dan direktori yang namanya dimulai dengan sebuah titik dan karakter khusus; misalnya, .@fooatau ..c.
Scott
Itulah mengapa saya menunjukkan bahwa itu berfungsi jika karakter kedua adalah alfanumerik. ;)
gaboroncancio