Ketika mencoba mengonversi beberapa file menjadi huruf kecil, saya perhatikan sesuatu yang terasa aneh bagi saya.
Saat menjalankan ini di bash:
find . -iname 'test' | while IFS='\n' read item; do mv $item $(echo $item | tr [:upper:] [:lower:]); done
Dan sumber dan target tidak berubah untuk mv, saya mendapatkan kesalahan berikut:
mv: cannot move '.test' to a subdirectory of itself, './test/test'
Dimana ./test/test
berasal dari? Saat gema bukannya mengeksekusi mv, saya mengerti mv ./test ./test
. Saya menguji ini pada FreeBSD 10 dan Debian 8.2.0 dengan hasil yang sama. Apa yang saya lewatkan?
./*
berbeda dari.
?./*
akan memperluas ke setiap item dalam direktori sementara.
akan mengambil direktori saat ini, tetapi pada akhirnya itu masih bergerak dalam direktori yang sama. Mari ambil direktoridir
misalnya yang berisi 5 direktoria
,b
,c
,d
dane.
Jika saya ingin mengganti nama semua subdirektori daridir
,find .
danfind ./*
akan mengembalikan hasil yang sama.dir
.-iname test
tidak cocok.test
; sudah jelas dari hasil kedua (dengan gema) bahwa itu benar-benar./test
dan hanya salah kutip.-ilname
persis sama dengan-iname
kecuali untuk tautan simbolis yang tidak terlibat di sini../*
biasanya diperluas ke semua entri di.
KECUALI mereka yang memulai.
(dot), meskipun beberapa shell memiliki opsi untuk mengubahnya, dibash
shopt -s dotglob
. OTOHfind .
akan selalu terlihat seperti dotnames./.profile
(Selain daripada.
dan..
), meskipun di sini nama seperti itu tidak cocok dengan-iname
.Jawaban:
Jika nama sudah dalam huruf kecil, itu akan diberikan ke perintah mv dua kali, seperti yang Anda lihat
Jika argumen terakhir ke mv adalah direktori, itu akan diperlakukan sebagai direktori tujuan di mana semua entitas bernama lainnya harus dipindahkan.
mv test test
pertama akan memeriksa argumen terakhir, apakah ada dan, jika demikian, apakah itu direktori. Dalam hal ini, maka mv akan memeriksa apakah itu titik mount yang sama (jika tidak, yaitu tujuannya adalah perangkat yang berbeda, perlu menyalin file kemudian menghapus yang asli); dalam hal ini, ya. Jadi mv membangun urutanrename(2)
syscalls, menambahkan semua nama sumber pada gilirannya ke direktori yang ditentukan sebagai tujuan:mv a b c d/
akan menghasilkanrename("a", "d/a")
,rename("b", "d/b")
, danrename("c", "d/c")
- jadi tentu sajamv test test
akan mencoba meneleponrename("test", "test/test");
. Yang jelas merupakan kesalahan, Anda tidak dapat memindahkan direktori di dalamnya.Untuk memperbaiki masalah Anda, buat perintah mv tergantung pada nama baru yang berbeda dan belum ada (jika Anda memiliki dua file berbeda yang disebut "Test" dan "test", Anda mungkin tidak ingin mengganti yang kedua tanpa bertanya). Tanpa saya menguji ini, dan mengetiknya di telepon, akan terlihat seperti ini:
new="$(echo "$old" | tr ...)"; [[ $new != $old && ! -e $new ]] && mv "$old" "$new"
(perhatikan kutipannya, Anda tidak ingin spasi pada nama memberi Anda pengantin metaforis).sumber