Bagaimana cara menyalin nama file yang dimulai dengan titik?

26

Saya mencoba menyalin semua file di bawah direktori A ke direktori B. Semua file di dalam direktori A mulai dengan titik, misalnya:

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

yang saya temukan jika saya gunakan cp A/* B:, selalu mendapatkan kesalahan:

cp: cannot stat 'A/*': no such file or directory

Tampaknya tidak ada pilihan untuk cpsebagai lsuntuk menangani entri dimulai dengan dot, ada orang yang tahu bagaimana cara memperbaikinya?

pengguna59285
sumber

Jawaban:

34

Alasannya adalah karena di bash, *tidak termasuk file yang dimulai dengan dot ( .).

Anda bisa lari

cp A/.* B

Ini akan memperingatkan Anda bahwa itu tidak menyalin .atau .., atau subdirektori, tetapi ini baik-baik saja.

Atau, jika Anda ingin menyalin file dot dan file normal bersamaan, jalankan

cp A/.* A/* B

Anda juga bisa berlari

shopt -s dotglob
cp A/* B

yang akan bekerja bash, tetapi tidak sh.

Dan jika Anda tidak keberatan subdirektori juga disalin, maka ini adalah yang termudah:

cp -R A/ B

Kiat: Jika wildcard tidak melakukan apa yang Anda harapkan, coba jalankan dengan gema, misalnya

$ echo A/*
A/file1 A/file2

$ echo A/.*
A/. A/.. A/.hidden1 A/.hidden2

$ echo A/.* A/*
A/. A/.. A/.hidden1 A/.hidden2 A/file1 A/file2

$ shopt -s dotglob
$ echo A/*
A/file1 A/file2 A/.hidden1 A/.hidden2
Mikel
sumber
Itu hanya masalah jika Anda menggunakannya -r. Tanpa -r, itu hanya akan melewatkan direktori.
Mikel
Dan contoh yang saya berikan menggunakan -Rharus bekerja dengan baik juga. Jika Anda pikir itu salah, tolong jelaskan mengapa.
Mikel
7

Jika bash, Anda dapat mengatur dotglobsebelum Anda menyalin

shopt -s dotglob
cp A/* /destination

Atau bahasa pemrograman

$ ruby -rfileutils -e  'Dir[".*"].each {|x| FileUtils.copy(x,"/destination") if File.file?x}'

Jika Anda tidak ingin mengatur dotglob, cukup

cp A/.* /destination 2>/dev/null

sumber
Menggunakan dotglob OP juga akan menyalin semua file yang tidak disembunyikan, yang tidak diinginkannya.
peoro
@peoro, Anda harus membaca pertanyaan itu lagi. Semua file Ayang disembunyikan. Dia hanya ingin menyalinnya.
7

Apa yang Anda cari lebih sesuai:

cp A/.??* B/

Ini akan cocok dengan semua file dot, tetapi tidak "." atau "..". Sebagian besar solusi di atas baik-baik saja selama Anda tidak bekerja secara rekursif. Tetapi segera setelah Anda ingin melakukan sesuatu seperti:

cp -R A/.??* B/

Tanpa menghilangkan ".." Anda akan menyalin semuanya dari direktori induk ke bawah, termasuk non-dotfile.

John Westlund
sumber
1
Ini akan melewatkan file-file dot yang merupakan karakter tunggal, seperti .aatau .x. Pola globbing terpendek Saya telah menemukan bahwa pertandingan setiap titik berkas kecuali .dan ..adalah .[^.]*.
pavon
2

Saya justed mencoba yang berikut ini dan berhasil hanya menemukan ...

cp A/.* B/
Andrew White
sumber
2
Ini juga akan lulus A/.dan A/..sebagai parameter untuk cp, yang bisa bermasalah jika OP juga perlu menyalin direktori (menggunakan cp -r)
peoro
2

Itu bukan cp's kesalahan , itu bash: pesta mengembang *di semua non-tersembunyi (yaitu: non awal dengan .) file.

Bash akan berkembang .*(dengan demikian A/.*, dalam kasus Anda) dengan semua file yang dimulai dengan ., tetapi sayangnya itu juga termasuk .dan ..(direktori sekarang dan induk) yang Anda mungkin ingin lewati. (Perhatikan bahwa shell lain, seperti zsh, tidak akan memasukkannya, dan IIRC juga bash, setelah mengatur beberapa opsi).

Solusi mudah bisa dengan menghapus .dan ..dari file yang cocok dengan .*, dengan cara (sangat) seperti ini:

cp $( for F in A/.*; do echo $F | grep -v "^\.*$"; done ) B

atau yang ini (mungkin lebih bersih: digunakan finduntuk mencari file yang akan disalin):

cp $( find A -maxdepth 1 -mindepth 1 -name ".*" ) B

tetapi Anda mungkin akan menemukan solusi yang lebih bersih.

peoro
sumber
mengapa Anda harus menggunakan for loopdan kemudian membuat grepproses tambahan hanya untuk melakukan pekerjaan seperti cp A/.*? cpakan mengabaikan "." dan ".." direktori.
1

Jika semuanya dimulai dengan titik, cukup gunakan A/.*:

[holt@Michaela test]$ cp A/* B
cp: cannot stat `A/*': No such file or directory

[holt@Michaela test]$ cp A/.* B
cp: omitting directory `A/.'
cp: omitting directory `A/..'
[holt@Michaela test]$ ls -al B
total 8
drwxrwxr-x. 2 holt holt 4096 2011-03-31 16:57 .
drwxrwxr-x. 4 holt holt 4096 2011-03-31 16:57 ..
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .a
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .b
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .c

Semoga ini membantu!

Xavier Holt
sumber
1

Anda dapat menggunakan skrip ini

IFS = $ '\ n'; untuk bertindak dalam $ (temukan A -d 1); jangan cp -R "$ act" B; selesai

Teka-teki
sumber
0

salinan:

cp A/.* B

daftar:

ls -l A/.*

daftar file tanpa direktori menurun:

ls -ld A/.*
Blek Geek
sumber
0

Anda harus mengecualikan. dan .. dari daftar file yang diteruskan ke cp!

Ini aman:

ls -1d A/.[a-zA-Z]* | xargs -i cp -rp {} B
AmitP
sumber
0

Ini adalah utas lama ... tapi saya selalu bisa menyalin semua file. Termasuk file / folder yang dimulai dengan '.'

Contoh akan menyalin semua file dan folder:

cp -aup /root/.* / backup / root /

Ontologik
sumber