Tekan keluaran baris perintah


118

Saya memiliki file batch sederhana seperti ini:

bergema

taskkill / im "test.exe" / f> nul

berhenti sebentar

Jika "test.exe" tidak berjalan, saya mendapatkan pesan ini:

EROR: Proses "test.exe" tidak ditemukan.

Mengapa pesan kesalahan ini ditampilkan, meskipun saya telah mengarahkan keluaran ke NUL?

Bagaimana saya bisa menekan keluaran itu?

Jawaban:


212

Karena pesan error sering stderrtidak masuk stdout.

Ubah permintaan menjadi ini:

taskkill /im "test.exe" /f >nul 2>&1

dan semuanya akan menjadi lebih baik.

Itu berfungsi karena stdoutdeskriptor file 1, dan stderrdeskriptor file 2 menurut konvensi. (0 adalah stdin, kebetulan.) 2>&1File keluaran deskriptor 2 salinan dari nilai baru 1, yang baru saja dialihkan ke perangkat null.

Sintaks ini (secara longgar) dipinjam dari banyak shell Unix, tetapi Anda harus berhati-hati karena ada perbedaan halus antara sintaks shell dan CMD.EXE.

Pembaruan: Saya tahu OP memahami sifat khusus dari "file" bernama NULsaya menulis di sini, tetapi pemberi komentar tidak dan jadi biarkan saya ngelantur dengan sedikit lebih detail tentang aspek itu.

Kembali ke rilis MSDOS yang paling awal, nama file tertentu diawali oleh kernel sistem file dan digunakan untuk merujuk ke perangkat. Daftar awal nama yang termasuk NUL, PRN, CON, AUXdan COM1melalui COM4. NULadalah perangkat nol. Itu selalu dapat dibuka untuk membaca atau menulis, jumlah berapa pun dapat ditulis di atasnya, dan pembacaan selalu berhasil tetapi tidak mengembalikan data. Yang lainnya termasuk port printer paralel, konsol, dan hingga empat port serial. Pada MSDOS 5, ada beberapa nama yang dicadangkan, tetapi konvensi dasarnya sudah ditetapkan dengan sangat baik.

Ketika Windows dibuat, itu memulai kehidupan sebagai lapisan pengalihan aplikasi yang cukup tipis di atas kernel MSDOS, dan dengan demikian memiliki batasan nama file yang sama. Ketika Windows NT dibuat sebagai sistem operasi yang sebenarnya dengan sendirinya, nama-nama seperti NULdan COM1terlalu banyak diasumsikan berfungsi untuk mengizinkan penghapusannya. Namun, gagasan bahwa perangkat baru akan selalu mendapatkan nama yang akan memblokir pengguna di masa mendatang dari nama-nama itu untuk file sebenarnya jelas tidak masuk akal.

Windows NT dan semua versi berikutnya (2K, XP, 7, dan sekarang 8) semuanya mengikuti menggunakan NT Namespace yang jauh lebih rumit dari kode kernel dan untuk kode ruang pengguna yang dibuat dengan hati-hati dan sangat non-portabel. Di ruang nama itu, driver perangkat terlihat melalui \Devicefolder. Untuk mendukung kompatibilitas mundur yang diperlukan, terdapat mekanisme khusus yang menggunakan \DosDevicesfolder yang mengimplementasikan daftar nama file yang dicadangkan di folder sistem file apa pun. Kode pengguna dapat menelusuri ruang nama internal ini menggunakan lapisan API di bawah API Win32 biasa; alat yang baik untuk menjelajahi namespace kernel adalah WinObj dari grup SysInternals di Microsoft.

Untuk penjelasan lengkap tentang aturan seputar nama legal file (dan perangkat) di Windows, halaman di MSDN ini akan menjadi informatif dan menakutkan. Aturannya jauh lebih rumit daripada yang seharusnya, dan sebenarnya tidak mungkin untuk menjawab beberapa pertanyaan sederhana seperti "berapa panjang nama jalur legal yang memenuhi syarat sepenuhnya terpanjang?".


5
Terima kasih atas jawabannya, dan yang terpenting untuk penjelasannya.
JosephStyons

Rekomendasi: taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul. Ini akan mencegah file kosong kosong ditempatkan ke direktori lokal
Samy Bencherif

11
@SamyBencherif, NULadalah nama file yang dicadangkan, dan dipetakan ke perangkat NUL. Anda tidak dapat membuat file aktual dengan nama NULdi direktori mana pun.
RBerteig

7

Gunakan skrip ini sebagai gantinya:

@taskkill/f /im test.exe >nul 2>&1
@pause

Apa yang 2>&1sebenarnya dilakukan bagian itu, adalah mengalihkan stderroutput ke stdout. Saya akan menjelaskannya lebih baik di bawah ini:

@ taskkill / f / im test.exe> ​​nul 2> & 1

Hentikan tugas "test.exe". Alihkan stderrke stdout. Lalu, alihkan stdoutke nul.

@berhenti sebentar

Tampilkan pesan jeda Press any key to continue . . . sampai seseorang menekan tombol.

CATATAN: @Simbol menyembunyikan prompt untuk setiap perintah. Anda dapat menghemat hingga 8 byte dengan cara ini.

Versi terpendek script Anda bisa:
@taskkill/f /im test.exe >nul 2>&1&pause
The &karakter digunakan untuk pengalihan pertama kalinya, dan untuk memisahkan perintah kedua kalinya.
Sebuah @karakter tidak diperlukan dua kali dalam garis. Kode ini hanya 40 byte, meskipun yang Anda posting adalah 49 byte! Saya sebenarnya menghemat 9 byte. Untuk kode yang lebih bersih, lihat di atas.


Ya, saya tahu setengah dari posting sebenarnya adalah cara mempersingkat kode Anda.
EKons

3

mysqldump tidak bekerja dengan: > nul 2> & 1
Sebagai gantinya gunakan: 2> nul
Ini menyembunyikan pesan stderr: "Peringatan: Menggunakan kata sandi pada antarmuka baris perintah dapat menjadi tidak aman"


0

Anda juga dapat melakukan ini:

tasklist | find /I "test.exe" > nul && taskkill /f /im test.exe > nul

Meskipun konteks pertanyaannya adalah skrip batch, saya menemukan bahwa di PowerShell sintaks di atas gagal dengan " out-file: FileStream diminta untuk membuka perangkat yang bukan file. Untuk dukungan perangkat seperti 'com1:' atau 'lpt1: ', panggil CreateFile, lalu gunakan konstruktor FileStream yang menggunakan pegangan OS sebagai IntPtr. "Solusinya adalah mengganti > nuldengan >$null.
bendung
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.