Bagaimana saya membuat rm tidak memberikan kesalahan jika file tidak ada?

321

Saya sedang menulis makefile yang akan membersihkan beberapa file yang tidak berguna di akhir kompilasi. Jika target telah dibuat, tentu saja akan melewati target itu dan file yang tidak berguna mungkin tidak ada di sana. Jadi jika saya melakukan ini:

rm lexer.ml interpparse.ml interpparse.mli

Saya mungkin mendapatkan kesalahan karena salah satu file tidak ada. Apakah ada cara rmuntuk mengabaikan file-file ini?

Dalam membaca halaman manual, saya melihat opsi berikut:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

Kedengarannya hampir seperti yang saya inginkan, tetapi saya tidak begitu yakin tentang bagian izin. Apakah ada cara untuk melakukan ini?

Jason Baker
sumber
Apakah Anda mencoba beberapa rmdi kotak pasir? Sepertinya -fmelakukan persis apa yang Anda inginkan, terlepas dari globbing.
JMD
Jika izin tidak mengizinkannya, rm akan dengan -fopsi masih mencoba menghapusnya. Itu akan gagal. Itu tidak akan memberitahu Anda itu gagal. Berguna jika nama file adalah variabel atau gumpalan.
LawrenceC
hanya untuk kelengkapan: ada rm --interactive=neveryang bertindak seperti rm -fkecuali itu mengembalikan status keluar kesalahan. lihat di sini untuk detail lebih lanjut: unix.stackexchange.com/questions/72864/…
lesmana

Jawaban:

275

The -fpilihan adalah pasti apa yang ingin Anda gunakan.

Konfirmasi tentang izin file yang dimaksud adalah ini:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

Jadi rmakan memperingatkan Anda jika Anda mencoba menghapus file yang tidak memiliki izin tulis untuk Anda. Ini diperbolehkan jika Anda memiliki izin menulis pada direktori tetapi agak aneh, itulah sebabnya rmbiasanya Anda diperingatkan.

Dave Webb
sumber
1
Sebagian besar, tetapi tidak semua sistem akan bertanya (saya pikir). Beberapa membutuhkan -i.
DaveParillo
1
Jika Anda menginginkan pesan kesalahan, tetapi bukan kode keluar kesalahan, lihat jawabannya oleh Giel Berkers . Saya menggunakan set -edi semua skrip bash saya sehingga skrip keluar setelah perintah apa pun memberikan kesalahan. Saya sering ingin skrip memberi tahu saya jika rmmemberi kesalahan, tetapi tetap melanjutkan. berlanjut.
cledoux
119

Solusi lain adalah yang ini: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

Cukup tambahkan pernyataan-OR setelah perintah Anda:

rm -rf my/dir || true

Dengan cara ini, ketika pernyataan # 1 gagal (melempar kesalahan), jalankan pernyataan # 2, yang sederhana true.

Giel Berkers
sumber
3
Ini mencetak kesalahan dan melanjutkan eksekusi, yang diinginkan untuk kasus saya.
worldsayshi
7
Atau hanya rm -rf my/dir ||:untuk menjadi lebih ringkas ( :kependekan dari true)
Godsmith
Solusi yang lebih baik menurut saya. Mudah dilihat apa yang terjadi dan mengapa kode hasil diabaikan. Saya suka itu!
Mavamaarten
76

Saya jauh terlambat ke pesta, tapi saya menggunakan ini sepanjang waktu. Dalam makefile, tambahkan -ke awal baris untuk mengabaikan nilai pengembalian baris itu. Seperti itu:

-rm lexer.ml interpparse.ml interpparse.mli
Robert Li
sumber
9
Ini masih akan mencetak kesalahan ke konsol, yang melatih Anda untuk mengabaikan kesalahan dalam hasil keluaran, yang mungkin bukan yang Anda inginkan. rm -rf adalah pilihan yang lebih baik menurut saya.
Godsmith
@ Godsmith Saya lebih suka mengabaikan kesalahan daripada memaksa menghapus rekursif. Ini bisa sangat nakal. Dan +1 untuk sintaksis khusus makefile
Daishi
Jika rm -rf bisa "nakal", itu berarti Anda menggunakan make di luar direktori di bawah kontrol versi. Mengapa?
Godsmith
Tolong beri tautan ke dokumentasi. Dapat menemukan deskripsi fitur ini.
George Sovetov
14

Jika Anda tidak ingin menggunakan opsi -f, alternatifnya adalah:

rm filethatdoesntexist 2> /dev/null 

Ini hanya akan menjaga kesalahan dari dicetak.

pengguna135299
sumber
7
Sayangnya ini masih akan memberikan kode keluar kesalahan.
Shaun McDonald
8

Jika Anda menemukan cara untuk membuat glob nama file, rmtidak akan mengeluh jika tidak dapat menemukan kecocokan. Jadi sesuatu seperti lexer.m* interpparse.*, dll. Harus bekerja untuk Anda (hati-hati, Anda tidak menghapus terlalu banyak, tentu saja). Juga, -fmerupakan cara yang masuk akal, selama Anda tidak berharap izin file akan menyelamatkan Anda dari menghapus file yang tidak Anda inginkan - jika Anda tidak ingin menghapusnya, jangan meletakkannya dalam daftar.

Nick Bastin
sumber
Globing akan keluar dari pertanyaan karena ada file lexer.mll yang tidak ingin saya hapus. Terima kasih telah menunjukkan mengapa -f masuk akal. Saya kira saya cenderung terlalu berhati-hati setelah terlalu banyak salah arah sudo rm -rf.
Jason Baker
Bahkan tidak lebih ketat lexer.m?...? Itu akan menangkap lexer.mldan lexer.mz, tetapi tidak lexer.mllatau lexer.mla.
JMD
1
@ JMD: Saya kira itu tergantung pada shell Anda dan dukungan pencocokan pola apa yang ditawarkannya untuk globbing.
Nick Bastin
6

Opsi -f berarti Anda tidak akan diminta jika ada sesuatu yang tidak diharapkan. Itu tidak berarti bahwa izin tidak diperhitungkan.

Jika Anda tidak memiliki cukup hak untuk menghapus file, itu tidak akan dihapus.

TETAPI , jika Anda memiliki cukup hak untuk mengubah hak istimewa, file Anda akan dihapus. Ini adalah kasus ketika Anda adalah pemilik file dengan izin hanya baca untuk pemilik (-r --------). Sebagai pemilik, Anda dapat chmod u+w, lalu menghapusnya: rm -fakan menghapus file itu.

mouviciel
sumber
4

Mungkin bisa membantu garis yang serupa dengan:

touch fakefile.exe fakefile.o && rm *.o *.exe

Saya tahu bahwa ini tidak terlalu pintar, tetapi berhasil.

Bogdan
sumber
3

Sebuah alternatif:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

Sayang sekali, Makefiles tidak dapat membagikan definisi fungsi shell di seluruh baris.

reinierpost
sumber
Sudahkah Anda mencoba menggunakan \ (garis miring terbalik) di akhir baris untuk membiarkannya melanjutkan di baris berikutnya?
beberapa
@some: Ya, mereka dapat tersebar di beberapa baris, tetapi untuk membagikannya di seluruh resep, Anda harus memasukkan definisi ke dalam variabel make.
reinierpost
3

Inilah yang saya gunakan dalam skrip shell. Itu menyembunyikan pesan kesalahan dan kode kesalahan.

rm doesnotexist 2> /dev/null || echo > /dev/null
teh_senaus
sumber
bagaimanarm doesnotexist 2&> /dev/null
user8162
1

Anda dapat menyentuh file sebelum Anda rm. itu akan membuat mereka jika mereka tidak ada :-)

touch lexer.ml interpparse.ml interpparse.mli
rm lexer.ml interpparse.ml interpparse.mli
commonpike
sumber
1

menulis kepada rm -rf ppp>/dev/null 2>&1 Anda yang lebih baru, dapatkan pesan kesalahan Masalah terjadi, jika error menghasilkan bukan ke STDERR 2 tetapi STDOUT 1 ... Ini terjadi ketika perintah menghasilkan bukan kesalahan tetapi peringatan. Anda perlu mengatur filter dan menghapus pesan ini. Tapi kasus ini biasa saja.

Anatoly
sumber
1

uji untuk melihat apakah file ada terlebih dahulu, jika ya, kemudian kirimkan ke rm. Maka kesalahan dari rm akan bermakna. -f atau mengabaikan pesan kesalahan biasanya lebih mencakup dari apa yang diinginkan seseorang. -Jika mungkin melakukan hal-hal yang tidak ingin Anda lakukan.

if [ -f lexer.ml ]; then
  rm lexer.ml
fi

tambahkan lebih banyak klausa uji jika ada lebih banyak file yang Anda ingin pastikan ada.


sumber