Dapatkah saya menggunakan mv file1 file2
cara yang hanya bergerak file1
untuk file2
jika file2
tidak ada?
Saya sudah mencoba
yes n | mv -i file1 file2
(ini memungkinkan mv
bertanya apakah file2 harus diganti dan secara otomatis menjawab tidak) tetapi selain menyalahgunakannya -i
juga tidak memberi saya kode kesalahan yang bagus (selalu 141 bukannya 0 jika dipindahkan dan sesuatu yang lain jika tidak dipindahkan)
pipefail
opsi sebagai 141 akan menjadi status keluaryes
, bukanmv
yang tidak punya alasan untuk mendapatkan SIGPIPE di sini.-T
untuk itu.mv
daripada daripada ituyes
, solusi paling sederhana mungkinmv -i file1 file2 < <(yes n)
Jawaban:
mv -vn file1 file2
. Perintah ini akan melakukan apa yang Anda inginkan. Anda dapat melewati-v
jika Anda mau.-v
membuatnya menjadi verbose - mv akan memberi tahu Anda bahwa itu memindahkan file jika memindahkannya (berguna, karena ada kemungkinan file tidak akan dipindahkan)-n
hanya bergerak jika file2 tidak ada.Harap dicatat, bahwa ini bukan POSIX seperti yang disebutkan oleh ThomasDickey .
sumber
strace
menunjukkan bahwa ia menggunakan (pada sistem saya): stat ("file2", 0x7ffe3e705d10) = -1 ENOENT (Tidak ada file atau direktori seperti itu) lstat ("file1", {st_mode = S_IFREG | 0644, st_size = 0, ...}) = 0 lstat ("file2", 0x7ffe3e705a10) = -1 ENOENT (Tidak ada file atau direktori seperti itu) ganti nama ("file1", "file2") = 0 lseek (0, 0, SEEK_CUR) = -1 ESPIPE (Pencarian ilegal). Jadi mengganti nama tampaknya digunakan. @ StéphaneChazelas solusi tampaknya menjadi yang tepat jika Anda benar-benar ingin melakukannya dengan bebas.renameat2
mv -n
Dari
man mv
pada sistem GNU:Pada sistem FreeBSD:
sumber
Atau:
Hanya akan berjalan
mv
jikafile2
tidak ada. Perhatikan bahwa itu tidak menjamin bahwafile2
tidak akan ditimpa karenafile2
bisa saja dibuat antara tes danmv
, tetapi perhatikan bahwa setidaknya versi GNU saat inimv
dengan-i
atau-n
tidak memberikan jaminan itu baik (meskipun kondisi balapan lebih sempit di sana sejak cek dilakukan di dalammv
).Di sisi lain, ini portabel, memungkinkan Anda untuk membedakan antara kasus, dan berfungsi terlepas dari jenis
file2
file (reguler, pipa, bahkan direktori ).sumber
renameat2
yang dapat Anda beriRENAME_NOREPLACE
bendera. Saya percaya ini secara atomis memeriksa keberadaan file dan kemudian memindahkan file.Pendekatan bebas ras dengan GNU yang
ln
disediakanfile1
bukan dari jenis direktori :(Kecuali untuk bug di beberapa sistem file jaringan), yang menjamin bahwa tidak ada
file2
file yang akan ditimpa (atau jikafile2
adalah tipe direktori,file1
tidak akan dipindahkan ke dalamnya), karenalink()
panggilan sistem, bertentangan denganrename()
panggilan sistem akan gagal jika target ada.Namun, akan ada keadaan perantara di mana file tersebut ada sebagai
file1
danfile2
.The
-T
pilihan (untuk selalu melakukanlink("file1", "file2")
bahkan jikafile2
adalah direktori jenis) adalah GNU spesifik.Anda juga bisa menggunakan
link
perintah:Namun, jika
file1
merupakan symlink, tergantung pada implementasinya,file2
akan berupa hardlink ke symlink tersebut atau ke target symlink tersebut (pada Solaris, gunakan/usr/sbin/link
, bukan/usr/xpg4/bin/link
).sumber
renameat2
dengan flagRENAME_NOREPLACE
adalah atom?Anda juga dapat menggunakan
test -e name
yang akan mengembalikan true jika nama ada (terlepas dari file, direktori, atau symlink).Sebagai contoh:
sumber
ln -s doesnotexist exists; test -e exists || echo "does it really not exist?"
. Sama dengan misalnyaln -s /var/spool/cron/crontabs/. exists
(dan Anda bukan root atau anggota grup crontab).