Perintah like mv foo* ~/bar/
menghasilkan pesan ini di stderr jika tidak ada file yang cocok foo*
.
mv: cannot stat `foo*': No such file or directory
Namun, dalam skrip saya sedang mengerjakan kasus itu akan baik-baik saja, dan saya ingin menghilangkan pesan itu dari log kami.
Apakah ada cara yang bagus untuk mengatakan mv
diam meskipun tidak ada yang bergerak?
mv foo* ~/bar/ 2> /dev/null
?mv
. :) Tapi itu akan dilakukan, tentu saja.mv
implementasi mendukung-q
opsi untuk menenangkan mereka, tetapi itu bukan bagian dari spesifikasi POSIXmv
. Dalammv
GNU coreutils, misalnya, tidak memiliki opsi seperti itu.Jawaban:
Apakah Anda mencari ini?
sumber
set -e
(yang harus digunakan dalam setiap skrip shell) akan gagal. Anda dapat menambahkan|| true
untuk menonaktifkan pemeriksaan untuk satu perintah.set -e
tidak boleh digunakan di setiap skrip shell, dalam banyak kasus ini membuat manajemen kesalahan bahkan lebih kompleks daripada tanpa.Sebenarnya, saya tidak berpikir bahwa mematikan
mv
adalah pendekatan yang baik (ingat itu mungkin melaporkan Anda juga tentang hal-hal lain yang mungkin menarik ... misalnya hilang~/bar
). Anda ingin membisukannya hanya jika ekspresi glob Anda tidak memberikan hasil. Bahkan lebih tepatnya tidak menjalankannya sama sekali.Tidak terlihat sangat menarik, dan hanya berfungsi di
bash
.ATAU
hanya kecuali Anda berada
bash
dengannullglob
set. Anda membayar harga 3x pengulangan pola glob.sumber
foo*
ketika itu adalah satu-satunya di direktori saat ini yang cocok dengan bola duniafoo*
. Ini bisa diselesaikan dengan ekspresi gumpalan yang tidak cocok dengan dirinya sendiri secara harfiah, sulit. Misalnya[ 'fo[o]*' = "$(echo fo[o]*)" ] || mv fo[o]* ~/bar/
.find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/
- GNU
mv
memiliki opsi "tujuan pertama" yang bagus (-t
) danxargs
dapat melewatkan menjalankan perintahnya jika tidak ada input sama sekali (-r
). Penggunaan-print0
dan juga-0
memastikan tidak akan ada kekacauan ketika nama file mengandung spasi dan hal-hal "lucu" lainnya.sumber
-maxdepth
,-print0
,-0
dan-r
juga ekstensi GNU (meskipun beberapa dari mereka ditemukan dalam implementasi lainnya saat ini).mv
.Sangat penting untuk menyadari bahwa itu sebenarnya shell yang memperluas
foo*
ke daftar nama file yang cocok, jadi ada sedikit yangmv
bisa dilakukan sendiri.Masalahnya di sini adalah bahwa ketika gumpalan tidak cocok, beberapa cangkang seperti
bash
(dan kebanyakan cangkang mirip Bourne lainnya, bahwa perilaku buggy sebenarnya diperkenalkan oleh cangkang Bourne pada akhir 70-an) meneruskan pola kata demi kata ke perintah.Jadi di sini, ketika
foo*
tidak cocok dengan file apa pun, alih-alih membatalkan perintah (seperti shell pra-Bourne dan beberapa shell modern lakukan), shell melewatifoo*
file kata demi katamv
, jadi pada dasarnya memintamv
untuk memindahkan file yang disebutfoo*
.File itu tidak ada. Jika ya, itu akan benar-benar cocok dengan polanya, jadi
mv
melaporkan kesalahan. Jika polanya sudahfoo[xy]
,mv
bisa saja secara tidak sengaja memindahkan file yang disebutfoo[xy]
bukanfoox
danfooy
file.Sekarang, bahkan di shell yang tidak memiliki masalah (pre-Bourne, csh, tcsh, fish, zsh, bash -O failglob), Anda masih akan mendapatkan kesalahan
mv foo* ~/bar
, tetapi kali ini oleh shell.Jika Anda ingin menganggapnya bukan kesalahan jika tidak ada file yang cocok
foo*
dan dalam hal itu, tidak memindahkan apa pun, Anda ingin membuat daftar file terlebih dahulu (dengan cara yang tidak menyebabkan kesalahan seperti dengan menggunakannullglob
opsi beberapa kerang), dan kemudian hanya panggilanmv
daftar tidak kosong.Itu akan lebih baik daripada menyembunyikan semua kesalahan
mv
(seperti menambahkan2> /dev/null
akan) seolah-olahmv
gagal karena alasan lain, Anda mungkin masih ingin tahu mengapa.dalam zsh
Atau gunakan fungsi anonim untuk menghindari penggunaan variabel sementara:
zsh
adalah salah satu dari shell yang tidak memiliki bug Bourne dan melaporkan kesalahan tanpa menjalankan perintah ketika glob tidak cocok (dannullglob
opsi belum diaktifkan), jadi di sini, Anda bisa menyembunyikanzsh
kesalahan dan mengembalikan stderr untukmv
jadi Anda masih akan melihatmv
kesalahan jika ada, tetapi bukan kesalahan tentang gumpalan yang tidak cocok:Atau Anda dapat menggunakan
zargs
yang juga akan menghindari masalah jikafoo*
gumpalan akan berkembang menjadi terlalu banyak file.Dalam ksh93:
Dalam bash:
bash
tidak memiliki sintaks untuk mengaktifkannullglob
satu bola saja, danfailglob
opsi dibatalkannullglob
sehingga Anda akan memerlukan hal-hal seperti:atau mengatur opsi dalam subkulit untuk menyimpan harus menyimpannya sebelum dan mengembalikannya sesudahnya.
Di
yash
Di
fish
Di shell ikan, perilaku nullglob adalah default untuk
set
perintah, jadi itu hanya:POSIXly
Tidak ada
nullglob
opsi di POSIXsh
dan tidak ada array selain dari parameter posisi. Ada trik yang dapat Anda gunakan untuk mendeteksi apakah sebuah glob cocok atau tidak:Dengan menggunakan a
foo[*]
danfoo*
glob, kita dapat membedakan antara kasus di mana tidak ada file yang cocok dan yang di mana ada satu file yang disebutfoo*
(yangset -- foo*
tidak bisa dilakukan).Lebih banyak membaca:
sumber
Ini mungkin bukan yang terbaik tetapi Anda dapat menggunakan
find
perintah untuk memeriksa apakah folder kosong atau tidak:sumber
foo*
jalur pencarian literal kefind
.Saya berasumsi bahwa Anda menggunakan bash, karena kesalahan ini tergantung pada perilaku bash untuk memperluas gumpalan yang tak tertandingi untuk diri mereka sendiri. (Sebagai perbandingan, zsh memunculkan kesalahan saat mencoba memperluas gumpalan yang tak tertandingi.)
Jadi, bagaimana dengan solusi berikut ini?
Ini akan diam-diam mengabaikan
mv
ifls -d foo*
gagal, sementara masih mencatat kesalahan jikals foo*
berhasil tetapimv
gagal. (Hati-hati,ls foo*
bisa gagal karena alasan lain selainfoo*
tidak ada, misalnya, hak yang tidak mencukupi, masalah dengan FS, dll., Sehingga kondisi seperti itu akan diabaikan dalam keheningan oleh solusi ini.)sumber
bash
). +1 untuk memperhitungkan fakta yangmv
mungkin gagal karena alasan lain selainfoo*
tidak ada.ls
perintah tidak akan terlalu jelas bagi pembaca di masa depan, setidaknya tanpa komentar.)ls -d foo*
dapat kembali dengan status keluar non-nol untuk alasan lain juga, seperti setelahln -s /nowhere foobar
(setidaknya dengan beberapals
implementasi).Anda bisa melakukannya misalnya
mv 1>/dev/null 2>&1 foo* ~/bar/
ataumv foo* ~/bar/ 1&>2
Untuk lebih jelasnya lihat: http://mywiki.wooledge.org/BashFAQ/055
sumber
mv foo* ~/bar/ 1&>2
tidak membungkam perintah, ia mengirimkan apa yang seharusnya ada di stdout juga pada stderr./dev/null
denganNUL
1
dan apa2
artinya?Anda dapat menipu (mudah dibawa) dengan
perl
:sumber
Jika Anda akan menggunakan Perl, Anda bisa melakukannya:
atau sebagai one-liner:
(Untuk perincian
move
perintah, lihat dokumentasi untuk File :: Copy .)sumber
Sebagai gantinya
Anda dapat melakukan
Sederhana, mudah dibaca :)
sumber
cp
ataurm
diam jikafoo*
tidak ada.Apakah perintah di atas berhasil atau tidak, kita dapat menemukan status keluar dari perintah sebelumnya
jika output dari $ echo? selain 0 berarti perintah gagal jika output 0 berarti perintah berhasil
sumber