Bagaimana saya bisa memindahkan semua file dalam subdirektori secara rekursif ke satu direktori?

10

Saya mencoba mengumpulkan semua file di bawah direktori saat ini dan semua subdirektori ke satu direktori. Saya mencoba sesuatu seperti yang berikut ini

find -type f -exec mv {} collection/{} \; 

perintah di atas tidak akan berfungsi karena yang kedua {}memberikan path lengkap, bagaimana saya bisa mengumpulkan semua file?

Kelinci
sumber

Jawaban:

14

Hapus {}dari mv, mvakan menganggapnya sebagai direktori target mengabaikan direktori induk:

find -type f -exec mv {} collection/ \;
Lekensteyn
sumber
ohh itu tidak terjadi pada saya. terima kasih :)
Kelinci Kelinci
Seperti yang saya katakan dalam jawaban saya untuk pertanyaan ini, ini berpotensi ide yang buruk. Mungkin menggunakan argumen itu -maxdepth 1akan membantu.
loevborg
Kalau dipikir-pikir, sepertinya saya salah baca pertanyaan Anda :) Maaf.
loevborg
@loevborg: Saya telah menambahkan "secara rekursif" ke judul sekarang. Jika masih ada kebingungan, silakan edit dan tingkatkan :)
Lekensteyn
1
variasi yang lebih cepat dari jawaban ini adalahfind -type f -print0|xargs -0r mv -it colection/
hildred
5

Alih-alih menggunakan find(yang melakukan pekerjaan dengan baik), Anda juga bisa menggunakan shell untuk tujuan ini.

Katakan Anda ingin semua file dari $ PWD ke $ DEST. Upaya alami adalah:

mv $PWD/* $DEST

Bagaimana cara kerjanya? Ekspresi "$ PWD / *" meluas ke nama semua file dalam direktori itu. Fitur shell ini disebut "globbing". Argumen terakhir mvadalah direktori tujuan. Jika Anda memiliki banyak file, ini tidak akan berfungsi karena panjang baris perintah terbatas.

Tetapi solusinya memiliki masalah bahwa ia menghapus file dot - atau "tersembunyi" file, file dan direktori yang namanya dimulai dengan ".". Untuk mengatasi ini, Anda harus memberi tahu shell Anda untuk menyertakan dotfiles saat globbing. Untuk melakukan ini, gunakan

shopt -s dotglob

saat menggunakan bash(dan Anda mungkin menggunakan bashkecuali Anda telah mengubah default). Dalam shell ini, perintah di atas akan berfungsi untuk dotfile juga.

Selain itu, di zsh, Anda memiliki opsi untuk memilih ini berdasarkan kasus per kasus. Untuk melakukan ini, masukkan

setopt extendedglob

di Anda .zshrc. Maka Anda bisa menggunakannya

mv $PWD/*(D) $DEST

untuk memindahkan semua file, termasuk dotfiles. ("D" memiliki efek mengaktifkan sementara opsi "GLOB_DOTS").

Sekarang pertanyaan awal adalah memindahkan semua file biasa (bukan direktori) dari semua subdirektori dan subdirektori ke satu direktori. Ini dapat dilakukan dengan zsh:

mv $PWD/**/*(D.)

Di sini ungkapan **/*membuat globber turun secara rekursif ke subdirektori. The Dberarti "juga pilih dotfiles', yang .berarti 'hanya memilih file biasa, bukan direktori'.

loevborg
sumber
baik saya ingin kambuh ke semua sub-direktori juga, tapi terima kasih cara informasi ini berguna, temui situasi ini terlalu banyak kali :)
Kelinci Kelinci
Sebenarnya, find tidak berlebihan dalam hal ini, globbing akan memilih semua kecocokan, bukan hanya file, tetapi juga direktori. Jika Anda sedang kekhawatiran tentang kinerja, Anda juga bisa menggunakan sesuatu seperti: find -type f -exec mv -t collection/ {} +. Lihat halaman buku panduan tentang cara kerjanya.
Lekensteyn
Lekensteyn, kamu benar. Saya memperbarui jawabannya sekarang setelah saya mengerti pertanyaannya.
loevborg
2
Jawaban yang bagus, sayang sekali itu tidak terlalu relevan dengan pertanyaan :).
crazy2be