Bagaimana saya bisa mendapatkan mv (atau * wildcard) untuk memindahkan file tersembunyi?

133

Saya memigrasi direktori home saya dari sistem lama ke yang baru, dan tarball yang saya buat berisi semuanya, termasuk file tersembunyi seperti .bashrc. Namun, ketika saya memindahkan konten tarball yang tidak dibongkar (yang ada di / tmp) ke direktori home saya yang baru, file-file yang disembunyikan tidak menyalin ( mv /tmp/home/rcook/* /home/rcook/). Bagaimana saya bisa membuat saya memindahkan mereka?

Sebenarnya, saya pikir masalahnya bukan pada mv, tapi dengan bash's globbing. Jika saya melakukan ini:

mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/

Saya melihat ini:

a/:
.  ..  .foo

b/:
.  ..  bar

a/.footidak bergerak. Jadi bagaimana saya bisa mendapatkan * wildcard untuk menemukan file tersembunyi?

Ya, saya kira saya bisa mendekompres tarball langsung ke direktori home saya, tetapi tarball mendekompresi ke dalam home/rcook/..., dan saya ingin memastikan saya menimpa tarball baru .bashrc, dll. Dengan versi lama, yang disesuaikan, dan mengetahui bagaimana menemukan dan memindahkan file yang tersembunyi adalah keterampilan yang berharga. Saran?


Beberapa jawaban menyarankan melakukan sesuatu seperti mv src/.* dest/. Namun, saya mencoba ini pada direktori pengujian saya dan mendapat kesalahan. Dimulai dengan:

rcook$ ls -a a/ b/
a/:
.  ..  bar  .foo

b/:
.  ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
.  ..  bar

b/:
.  ..  .foo

Apa yang saya lakukan salah?

Randall Cook
sumber

Jawaban:

146

Kamu bisa melakukan ini :

shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/

Anda bisa meletakkannya

shopt -s dotglob

di Anda ~/.bashrcjika Anda ingin menjadi default.

Lihat http://mywiki.wooledge.org/glob


Pendekatan lain untuk menyalin file dot:

mv /tmp/home/rcook/.[!.]* /home/rcook/

Jangan gunakan pola ..*karena cocok ..(pointer ke direktori induk). Jika ada file yang namanya dimulai dengan dua titik ( ..something), gunakan juga pola ..?*.

Gilles Quenot
sumber
Silakan periksa tambahan yang saya taruh di bagian bawah pertanyaan saya. Terima kasih.
Randall Cook
1
Tidak ada yang salah, .dan dir.. spesial: masing-masing dir & dir orangtua saat ini . Itu hanya peringatan. shopt -s dotglobSolusi penggunaan yang lebih baik
Gilles Quenot
Saya akhirnya hanya melakukan dua gerakan: mv home/rcook/* /home/rcook/diikuti oleh mv home/rcook/.* /home/rcook/. Ini berhasil, meskipun saya berharap saya telah mengikuti tautan dan membaca tentang mode dotglob terlebih dahulu. Itu akan menyelamatkan saya selangkah. +1
Randall Cook
Jadi pendekatan kedua membutuhkan penggunaan jalur absolut?
franzlorenzon
3
Jika Anda menggunakan zsh, Anda dapat menggunakan yang Dkualifikasi globbing atau yang GLOB_DOTSopsi shell .
mgalgs
43

Dalam penambahan Anda, Anda mendapat kesalahan tetapi kode masih berfungsi. Satu-satunya hal yang ditambahkan adalah bahwa Anda memberi tahu itu hanya untuk menyalin file dot. Mencoba:

mv src/* src/.* dst/

Anda masih akan mendapatkan kesalahan untuk. dan .. entri, yang baik-baik saja. Tetapi langkah itu harus berhasil.

~/scratch [andrew] $ mv from/* from/.* to/
mv: cannot move from/.’ to to/.’: Device or resource busy
mv: cannot remove from/..’: Is a directory
~/scratch [andrew] $ ls -a from/ to/
from/:
.  ..

to/:
.  ..  test  .test
Andrew Schwartz
sumber
1
Poin bagus, @AndrewSchwartz. Saya suka pendekatan ini juga. Saya pikir itu layak mendapat pengakuan lebih.
Randall Cook
Saya suka @Drake Clarris menjawab sedikit lagi, karena saya menjalankan di Amazon AWS CodeBuild dan kode pengembalian bukan nol sebenarnya menyebabkan build saya berhenti. Saya akhirnya memindahkan satu .hiddenfile yang saya miliki secara eksplisit untuk menyelesaikan masalah saya.
HeyWatchIni
Jika kode keluar non-nol adalah masalah yang Anda bisa menekannya, misalnya dengan menambahkan || :( ||berarti menjalankan yang berikut ini pada false / error, :adalah perintah noop). Tetapi itu juga akan menekan kesalahan yang sah, misalnya folder tujuan tidak ada. Saya tidak dapat menemukan cara yang lebih elegan mvuntuk mengecualikan .dan ..entri. Butt plus besar bagi saya lebih dari cp tidak menulis file baru ke disk.
Andrew Schwartz
10

Jika Anda berada ls -ldalam direktori, Anda akan melihat .dan di ..antara file-file yang terdaftar. Jadi, saya pikir mv .* /destmemperhitungkan petunjuk itu. Mencoba:

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/

ini akan mengabaikan pointer dir saat ini dan orang tua.

Anda akan mendapatkan kesalahan jika salah satu dari tiga pola *, [^.]*atau ..?*tidak cocok dengan file, jadi Anda hanya harus menyertakan yang cocok.

Azamat
sumber
Bagus. Jawaban serupa untuk gaya globbing ini ada di sini: superuser.com/a/784046/144977 . Terima kasih telah memposting ini.
phyatt
7

Dua kemungkinan solusi yang bisa saya pikirkan. Yang pertama adalah menggunakan cp sebagai gantinya dengan opsi rekursif, menyalin direktori saat ini ke tujuan.

cp -Rp . /desired/directory

maka Anda dapat menghapus file sumber di direktori saat ini

Atau, jika Anda tahu file-file tersebut dinamai secara waras (tanpa spasi, wildcard, karakter yang tidak dapat dicetak), Anda dapat melakukan sesuatu seperti ini

mv $(ls -A) /desired/directory
Drake Clarris
sumber
4
Copy-then-remove sangat berbeda dari move jika sumber dan target berada pada sistem file yang sama. Setidaknya termasuk opsi -puntuk melestarikan metadata. Penggunaan lsharus menjadi pilihan terakhir, dan di sini ada cara yang lebih baik dan lebih sederhana.
Gilles
2

Sebenarnya tidak ada yang namanya "tersembunyi" file di Linux. File yang dimulai dengan titik hanya disembunyikan dari daftar file secara default.

Untuk menyalin file bahkan dengan glob, Anda perlu awalan file dengan .seperti mv -u .* foodan kemudian .fooakan belajar seperti foo/.fooketika dipindahkan.

Opsi -u hanya akan memindahkan file ketika sumber lebih baru, atau tujuan hilang. Atau Anda bisa mengabaikan kesalahan tentang memindahkan .dan ..karena mereka adalah file khusus dan tidak dapat dipindahkan, tetapi jangan terjebak dalam .*glob oleh shell.

dobey
sumber
Silakan periksa tambahan yang saya taruh di bagian bawah pertanyaan saya. Terima kasih.
Randall Cook
0

Jadi kita punya:

a
|-- .foo
`-- bar

dan:

b

Saya menghabiskan banyak waktu untuk menemukan solusi yang lebih baik daripada semua jawaban di sini.

Kemudian saya mengambil 30 detik untuk perintah ini:

$ mv --help

Lalu aku menemukan cintaku:

$ mv a/ b/ -T

Catatan: Saya bahkan tidak mengerti argumennya -T. Itu hanya melakukan apa yang saya butuhkan. Di sini tertulis:

-T, --no-target-direktori memperlakukan DEST sebagai file normal

pengguna433901
sumber
1
Jika Anda menghilangkan garis miring, Anda seharusnya tidak perlu -T. Either way ini pada dasarnya memberitahu saya untuk memindahkan direktori itu sendiri, daripada memindahkan semua file dari dalamnya.
thomasrutter
@ thomasrutter, bukankah memindahkan direktori itu sendiri sama dengan mengganti namanya?
Randall Cook
3
Ya, jika tujuan induk tetap sama, itu pada dasarnya hanya mengubah nama saja. Bagaimanapun Anda merujuknya, itu mungkin tidak membantu menjawab pertanyaan awal, yaitu tentang memindahkan file di dalam direktori ke lokasi tertentu.
thomasrutter
0

Dalam kasus saya, saya hanya mencoba mvsatu file tersembunyi dan ini solusinya:

FILE=.myHiddenFile
mv "$FILE" dest/

Penjelasan

Awalnya saya mencoba:

mv .myHiddenFile dest/

Tapi itu terus menghasilkan kesalahan:

mv: cannot stat '.myHiddenFile': No such file or directory

Meskipun ls -almenunjukkan bahwa file dan dest/ada.

Alasannya tampaknya karena shell menafsirkan "." dalam nama file, jadi dengan memindahkannya ke variabel, ia menghindari interpretasi. Mungkin ada cara lain untuk menyelesaikan ini, tetapi ini sudah cukup bagi kami.

Yesaya
sumber
-1

Jika Anda ingin menyalin file termasuk file tersembunyi ke direktori saat ini Anda berada.

cp -Rp source-directory/. .
Rick
sumber
1
Ini sangat mirip dengan jawaban Drake Clarris dari tahun 2013. Apakah Anda memiliki hal lain untuk ditambahkan?
Randall Cook