Tantangan : menulis file skrip tunggal foo.cmd
yang dapat dipanggil dari cmd.exe
prompt vanilla Windows (bukan PowerShell, bukan dalam mode administrator), untuk mengeksekusi kode khusus Windows sewenang-wenang ...
> .\foo.cmd
Hello Windows!
... tetapi juga akan dipanggil berubah dari khas POSIX-compliant (Linux / OSX) shell prompt ( bash
, tcsh
, atau zsh
), untuk mengeksekusi sewenang-wenang kode POSIX-spesifik:
$ chmod a+x foo.cmd
$ ./foo.cmd
Hello POSIX!
... tanpa memerlukan instalasi atau pembuatan juru bahasa / alat pihak ketiga.
Saya tahu ini mungkin, tetapi dengan cruft (yaitu pada Windows, satu atau dua baris sampah / pesan kesalahan dicetak ke stderr atau stdout sebelum "Hello Windows!").
Kriteria yang menang adalah minimalisasi (pertama) jumlah baris cruft, dan (kedua) jumlah karakter cruft.
Cruft dapat didefinisikan sebagai output konsol (stdout atau stderr) yang tidak diproduksi oleh kode muatan (sewenang-wenang). Baris kosong dihitung dalam jumlah baris. Baris baru tidak dihitung dalam jumlah karakter. Skor Cruft harus dijumlahkan di kedua platform. Mari kita abaikan mekanisme seperti cls
itu menyapu cruft tetapi dengan mengorbankan juga keluaran terminal sebelumnya. Jika Windows menggemakan perintah Anda karena Anda belum mengaktifkannya @echo off
, mari kita kecualikan karakter yang dihabiskannya dalam mencetak direktori saat ini dan meminta.
Kriteria sekunder adalah kesederhanaan / keanggunan solusi di dalamnya foo.cmd
: jika "infrastruktur" didefinisikan sebagai karakter apa pun yang tidak terlibat langsung dalam kode muatan sewenang-wenang, maka minimalkan terlebih dahulu jumlah baris yang berisi karakter infrastruktur, dan kedua jumlah total infrastruktur karakter.
Kudos ekstra jika bagian POSIX akan berfungsi meskipun file memiliki akhiran CRLF! (Tidak yakin bahwa bagian terakhir bahkan mungkin.)
Solusi saya yang ada, yang akan saya posting di sini setelah orang lain memiliki kesempatan, menggunakan 6 baris kode infrastruktur (52 karakter termasuk baris baru). Ini menghasilkan 5 baris cruft, dua di antaranya kosong, yang semuanya terjadi pada Windows (30 karakter tidak termasuk baris baru dan tidak termasuk direktori saat ini / string prompt yang muncul pada dua baris tersebut).
Jawaban:
0 baris cruft, 0 cruft chars, 2 infra. baris, 21 infra. karakter, CRLF ok
Menghapus solusi lain.
17 karakter menggunakan
exit /b
dari jawaban Digital Trauma:sumber
: command not found
setiap kali baris kosong merayapi ke dalam posix payload, tetapi saya akhirnya menemukan bahwa itu bukan tentang:
pada baris pertama melainkan karena CRLF yang tidak dilindungi oleh#
. Bagi saya adalah berita bahwa sebuah#!
baris tidak diperlukan — yang bertanggung jawab atas dua baris Windows cruft dalam versi saya sebelumnya.: ` >&3` \
ke setiap baris payload, saya kira Anda bisa mengatakan biaya infrastrukturnya tinggi secara sewenang-wenang.#
perlu?Skor 0 cruft + 4 jalur infra + 32 infra karakter. LF & CRLF OKE.
Ini didasarkan pada apa yang saya temukan di blog ini , dengan bit Amiga dan garis yang tidak perlu lainnya dikeluarkan. Saya menyembunyikan baris DOS dalam tanda kutip komentar daripada menggunakan
\
baris berlanjut, sehingga ini dapat bekerja dengan CRLF dan LF.Dengan ujung baris DOS CRLF atau * nix LF, ia bekerja di Ubuntu, OSX dan anggur:
Untuk membuat ini persis (dengan CRLF) pada mesin * nix (termasuk OSX), rekatkan yang berikut ini ke terminal:
sumber
dosix
adalah nama yang bagus juga. Tetapi pada Mac saya (OS 10.9.4, Darwin Kernel Versi 13.3.0, GNU bash versi 3.2.51) gagal dijalankan dengan:./dosix.cmd: line 13: syntax error: unexpected end of file
Ada ide mengapa?Saya sudah memposting solusi yang telah saya gunakan, karena sudah dikalahkan. Ini milik seorang kolega saya yang saya pikir pasti telah membaca entri blog yang sama dengan Digital Trauma .
#!
telepon tidak peduli (jadi untuk penerjemah standar sepertish
dan teman-teman, gagal)sumber
#!
, yang berarti milik Anda adalah satu-satunya jawaban sejauh ini untuk menjadi skrip yang valid pada sistem POSIX. Tentu beberapa yang lain dapat dijalankan jika - tetapi hanya jika mereka dimulai dari shell dengan solusi untuk skrip yang salah.#!
garis yang hilang , tetapi mereka akan menggunakan shell yang berbeda untuk menafsirkan skrip. Itu berarti "skrip" yang tidak dimulai dengan#!
harus valid tidak hanya dalam satu shell, tetapi setiap shell yang masuk akal dapat ditafsirkan oleh. Tetapi yang lebih buruk, itu hanya bekerja ketika dimulai dari shell lain. Skrip seperti itu mungkin berfungsi dari baris perintah, tetapi tidak dalam konteks di mana Anda akhirnya bermaksud menggunakannya.#!
baris dalam jawaban saya yang diedit (1 garis infrastruktur dengan 21 karakter) dapat digabungkan dengan jawaban orang lain dengan biaya Windows hanya 2 baris (yang satu kosong) atau 23 karakter.Ringkasan / sintesis jawaban dan diskusi
Ini menyenangkan, dan saya belajar banyak.
Beberapa pengerjaan khusus Windows tidak dapat dihindari jika, pada sistem POSIX Anda, Anda perlu memulai skrip Anda dengan sebuah
#!
baris. Jika Anda tidak memiliki alternatif selain melakukan ini, maka baris ini:mungkin yang terbaik yang bisa didapat. Ini menyebabkan satu baris kosong dan satu baris cruft menjadi output pada konsol Windows. Namun, Anda mungkin dapat pergi tanpa
#!
garis: pada sebagian besar sistem, salah satu penerjemah shell yang biasa akan menjalankan skrip (masalahnya adalah tidak dapat diprediksi secara universal penafsir mana yang akan - tergantung pada, tetapi akan tidak harus identik dengan, shell yang Anda gunakan untuk menjalankan perintah).Di luar garis pertama yang rumit itu, ada beberapa solusi tanpa ampun yang benar-benar cerdik. Pengajuan pemenang oleh jimmy23013 hanya terdiri dari dua jalur infrastruktur pendek, dan memanfaatkan peran ganda
:
karakter untuk menerapkan garis "sunyi" pada kedua platform (sebagai no-op in -factosh
dan teman-teman, dan sebagai label penanda dicmd.exe
):Hal ini dimungkinkan untuk membuat script seperti berjalan di sistem POSIX bahkan meskipun CRLF line-ujung, tetapi untuk melakukan hal ini untuk sebagian besar penafsir Anda harus mengakhiri setiap baris bagian POSIX Anda (bahkan baris kosong) dengan komentar atau komentar karakter.
Akhirnya, berikut adalah dua varian solusi yang saya kembangkan berdasarkan masukan semua orang. Mungkin saja hampir yang terbaik dari semua dunia, karena mereka meminimalkan kerusakan dari kurangnya
#!
dan membuat kompatibilitas CRLF lebih lancar. Dibutuhkan dua jalur infrastruktur tambahan. Hanya satu baris (standar) yang harus ditafsirkan oleh shell POSIX yang tidak dapat diprediksi, dan baris itu memungkinkan Anda untuk memilih shell untuk sisa skrip (bash
dalam contoh berikut):Bagian dari keindahan dari solusi heredoc ini adalah bahwa mereka masih kuat-CRLF: selama
<<:Z
muncul di akhir baris, prosesor heredoc sebenarnya akan mencari, dan akan menemukan, token:Z\r
Sebagai twist terakhir, Anda dapat menyingkirkan komentar end-of-line yang sial dan tetap mempertahankan kekokohan CRLF, dengan menghapus
\r
karakter sebelum meneruskannya ke shell. Ini menempatkan sedikit lebih banyak kepercayaan pada shell yang tidak dapat diprediksi (akan lebih baik untuk digunakan{ tr -d \\r|bash;}
sebagai ganti(tr -d \\r|bash)
tapi kurung keriting adalah sintaks hanya-bash):Tentu saja, pendekatan ini mengorbankan kemampuan untuk menyalurkan input stdin ke dalam skrip.
sumber