Apakah mungkin untuk menulis satu file skrip yang dijalankan di Windows (diperlakukan sebagai .bat) dan Linux (melalui Bash)?
Saya tahu sintaks dasar keduanya, tetapi tidak mengetahuinya. Itu mungkin bisa mengeksploitasi sintaksis Bash yang tidak jelas atau beberapa kesalahan prosesor batch Windows.
Perintah yang akan dijalankan mungkin hanya satu baris untuk menjalankan skrip lainnya.
Motivasinya adalah hanya memiliki satu perintah boot aplikasi untuk Windows dan Linux.
Pembaruan: Kebutuhan untuk skrip shell "asli" sistem adalah ia harus memilih versi penerjemah yang tepat, menyesuaikan dengan variabel lingkungan terkenal tertentu, dll. Tidak disarankan untuk menginstal lingkungan tambahan seperti CygWin - Saya ingin mempertahankan konsepnya " unduh & jalankan ".
Satu-satunya bahasa lain yang perlu dipertimbangkan untuk Windows adalah Windows Scripting Host - WSH, yang telah disetel secara default sejak 98.
sumber
cp
, atau sebaliknya jadi menulis dua skrip terpisah mungkin secara pedagogis lebih baik daripada teknik lanjutan yang ditunjukkan di sini.Jawaban:
Apa yang telah saya lakukan adalah menggunakan sintaks label cmd sebagai penanda komentar . Karakter label, titik dua (
:
), sama dengantrue
di kebanyakan shell POSIXish. Jika Anda segera mengikuti karakter label dengan karakter lain yang tidak dapat digunakan dalam aGOTO
, maka mengomentaricmd
skrip Anda tidak akan memengaruhicmd
kode Anda .Retasannya adalah dengan meletakkan baris kode setelah urutan karakter "
:;
". Jika Anda kebanyakan menulis skrip satu baris atau, seperti yang mungkin terjadi, dapat menulis satu barissh
untuk banyak bariscmd
, berikut ini mungkin baik-baik saja. Jangan lupa bahwa penggunaan apa pun$?
harus sebelum titik dua berikutnya:
karena:
disetel ulang$?
ke 0.Contoh penjagaan yang sangat dibuat-buat
$?
:Ide lain untuk melompati
cmd
kode adalah dengan menggunakan heredocs sehinggash
memperlakukancmd
kode tersebut sebagai string yang tidak digunakan dancmd
menafsirkannya. Dalam kasus ini, kami memastikan bahwa pembatas heredoc kami dikutip (untuk berhentish
melakukan interpretasi apa pun pada kontennya saat menjalankan dengansh
) dan memulai dengan:
sehinggacmd
melompati seperti baris lain yang dimulai:
.Bergantung pada kebutuhan atau gaya pengkodean Anda, interlace
cmd
dansh
kode mungkin masuk akal atau tidak. Menggunakan heredocs adalah salah satu metode untuk melakukan interlace tersebut. Namun, ini dapat diperpanjang denganGOTO
teknik :Komentar universal, tentu saja, dapat dilakukan dengan urutan karakter
: #
atau:;#
. Spasi atau titik koma diperlukan karenash
dianggap#
sebagai bagian dari nama perintah jika bukan karakter pertama pengenal. Misalnya, Anda mungkin ingin menulis komentar universal di baris pertama file Anda sebelum menggunakanGOTO
metode untuk membagi kode Anda. Kemudian Anda dapat memberi tahu pembaca mengapa skrip Anda ditulis dengan sangat aneh:Jadi, beberapa ide dan cara untuk menyelesaikan
sh
dancmd
skrip -compatible tanpa efek samping yang serius sejauh yang saya tahu (dan tanpacmd
output'#' is not recognized as an internal or external command, operable program or batch file.
).sumber
.cmd
ekstensi, jika tidak maka tidak akan berjalan di Windows. Apakah ada solusi lain?.cmd
dan menandainya dapat dieksekusi. Dengan begitu, menjalankan skrip dari shell default di Windows atau unix akan berfungsi (hanya diuji dengan bash). Karena saya tidak dapat memikirkan cara untuk memasukkan shebang tanpa membuat cmd mengeluh dengan keras, Anda harus selalu memanggil skrip melalui shell. Yaitu, pastikan untuk menggunakanexeclp()
atauexecvp()
(menurut sayasystem()
melakukan ini dengan cara yang "benar" untuk Anda) daripadaexecl()
atauexecv()
(fungsi terakhir ini hanya akan bekerja pada skrip dengan shebang karena mereka lebih langsung ke OS).<Exec/>
MSBuild Task ) daripada sebagai file batch independen. Mungkin jika saya punya waktu di masa depan saya akan mengupdate jawaban dengan informasi di komentar ini…Anda bisa mencoba ini:
Mungkin Anda perlu menggunakan
/r/n
sebagai baris baru daripada gaya unix. Jika saya ingat benar, baris baru unix tidak diartikan sebagai baris baru oleh.bat
skrip. Cara lain adalah dengan membuat#.exe
file di jalur yang tidak melakukan apa pun di cara yang mirip dengan jawaban saya di sini: Apakah mungkin untuk menanamkan dan mengeksekusi VBScript dalam file batch tanpa menggunakan file sementara?EDIT
Jawaban binki hampir sempurna tapi masih bisa ditingkatkan:
Ini menggunakan lagi
:
trik dan komentar multi baris. Sepertinya cmd.exe (setidaknya di windows10) berfungsi tanpa masalah dengan EOL gaya unix jadi pastikan bahwa skrip Anda diubah ke dalam format linux. (pendekatan yang sama telah digunakan sebelumnya di sini dan di sini ). Padahal menggunakan shebang tetap akan menghasilkan keluaran yang mubazir ...sumber
/r/n
di akhir baris akan menyebabkan banyak sakit kepala dalam skrip bash kecuali Anda mengakhiri setiap baris dengan#
(yaitu#/r/n
) - dengan cara itu\r
akan diperlakukan sebagai bagian dari komentar dan diabaikan.# 2>NUL & ECHO Welcome to %COMSPEC%.
berhasil menyembunyikan kesalahan tentang#
perintah yang tidak ditemukan olehcmd
. Teknik ini berguna saat Anda perlu menulis baris mandiri yang hanya akan dieksekusi olehcmd
(mis., Dalam aMakefile
).Saya ingin berkomentar, tetapi hanya dapat menambahkan jawaban saat ini.
Teknik yang diberikan sangat bagus dan saya juga menggunakannya.
Sulit untuk menyimpan file yang memiliki dua jenis jeda baris yang terkandung di dalamnya, yaitu
/n
untuk bagian bash dan/r/n
untuk bagian windows. Kebanyakan editor mencoba dan menerapkan skema baris baru dengan menebak jenis file yang Anda edit. Juga sebagian besar metode mentransfer file melalui internet (terutama sebagai file teks atau skrip) akan mencuci jeda baris, jadi Anda bisa mulai dengan satu jenis jeda baris dan berakhir dengan yang lain. Jika Anda membuat asumsi tentang jeda baris dan kemudian memberikan skrip Anda kepada orang lain untuk digunakan, mereka mungkin merasa itu tidak berhasil untuk mereka.Masalah lainnya adalah sistem file yang dipasang di jaringan (atau CD) yang digunakan bersama di antara jenis sistem yang berbeda (terutama di mana Anda tidak dapat mengontrol perangkat lunak yang tersedia untuk pengguna).
Oleh karena itu, seseorang harus menggunakan jeda baris DOS
/r/n
dan juga melindungi skrip bash dari DOS/r
dengan memberi komentar di akhir setiap baris (#
). Anda juga tidak dapat menggunakan kelanjutan baris di bash karena/r
akan menyebabkannya putus.Dengan cara ini siapa pun yang menggunakan skrip, dan dalam lingkungan apa pun, skrip akan berfungsi.
Saya menggunakan metode ini bersama dengan membuat Makefile portabel!
sumber
Berikut ini berfungsi untuk saya tanpa kesalahan atau pesan kesalahan dengan Bash 4 dan Windows 10, tidak seperti jawaban di atas. Saya memberi nama file "terserah.cmd", lakukan
chmod +x
agar dapat dieksekusi di linux, dan membuatnya memiliki akhiran baris unix (dos2unix
) untuk menjaga bash tetap tenang.sumber
Anda dapat membagikan variabel:
sumber
Ada beberapa cara untuk menjalankan perintah yang berbeda pada
bash
dancmd
dengan skrip yang sama.cmd
akan mengabaikan baris yang dimulai dengan:;
, seperti yang disebutkan dalam jawaban lain. Ini juga akan mengabaikan baris berikutnya jika baris saat ini diakhiri dengan perintahrem ^
, karena^
karakter akan keluar dari jeda baris dan baris berikutnya akan diperlakukan sebagai komentar olehrem
.Sedangkan untuk membuat garis
bash
abaikancmd
, ada beberapa cara. Saya telah menyebutkan beberapa cara untuk melakukannya tanpa melanggarcmd
perintah:#
Perintah tidak ada (tidak disarankan)Jika tidak ada
#
perintah yang tersediacmd
saat skrip dijalankan, kita dapat melakukan ini:The
#
karakter pada awalcmd
merek garisbash
memperlakukan bahwa garis sebagai komentar.The
#
karakter pada akhirbash
baris digunakan untuk komentar pada\r
karakter, seperti Brian Tompsett tunjukkan dalam jawabannya . Tanpa ini,bash
akan memunculkan kesalahan jika file memiliki\r\n
akhiran baris, diperlukan olehcmd
.Dengan melakukan
# 2>nul
, kami menipucmd
untuk mengabaikan kesalahan dari beberapa#
perintah yang tidak ada , sambil tetap menjalankan perintah yang mengikuti.Jangan gunakan solusi ini jika ada
#
perintah yang tersedia diPATH
atau jika Anda tidak memiliki kendali atas perintah yang tersedia untukcmd
.Menggunakan
echo
untuk mengabaikan#
karakter dicmd
Kita dapat menggunakan
echo
dengan keluarannya yang diarahkan untuk memasukkancmd
perintah dibash
area yang dikomentari:Karena
#
karakter tidak memiliki arti khususcmd
, itu diperlakukan sebagai bagian dari teks keecho
. Yang harus kita lakukan adalah mengarahkan output dariecho
perintah dan memasukkan perintah lain setelahnya.#.bat
File kosongThe
echo >/dev/null # 1>nul 2> #.bat
garis menciptakan kosong#.bat
berkas sementara dicmd
(atau mengganti yang sudah ada#.bat
, jika ada), dan tidak apa-apa saatbash
.File ini akan digunakan oleh
cmd
baris berikutnya meskipun ada beberapa#
perintah lain diPATH
.The
del #.bat
perintah padacmd
kode -specific menghapus file yang telah dibuat. Anda hanya perlu melakukan ini dicmd
baris terakhir .Jangan gunakan solusi ini jika
#.bat
file mungkin ada di direktori kerja Anda saat ini, karena file itu akan dihapus.Direkomendasikan: menggunakan here-document untuk mengabaikan
cmd
perintah dibash
Dengan menempatkan
^
karakter di akhircmd
baris, kita keluar dari baris baru, dan dengan menggunakan:
sebagai pemisah dokumen di sini, konten baris pembatas tidak akan berpengaruhcmd
. Dengan begitu,cmd
hanya akan mengeksekusi barisnya setelah:
baris berakhir, memiliki perilaku yang sama sepertibash
.Jika Anda ingin memiliki banyak baris di kedua platform dan hanya mengeksekusinya di akhir blok, Anda dapat melakukan ini:
Selama tidak ada
cmd
garis yang tepathere-document delimiter
, solusi ini akan berhasil. Anda dapat mengubahhere-document delimiter
ke teks lain.Di semua solusi yang disajikan, perintah hanya akan dijalankan setelah baris terakhir , membuat perilakunya konsisten jika melakukan hal yang sama di kedua platform.
Solusi tersebut harus disimpan ke file dengan
\r\n
jeda baris, jika tidak, solusi tersebut tidak akan berfungsicmd
.sumber
Jawaban sebelumnya tampaknya mencakup hampir semua opsi dan banyak membantu saya. Saya menyertakan jawaban ini di sini hanya untuk mendemonstrasikan mekanisme yang saya gunakan untuk menyertakan skrip Bash dan skrip CMD Windows dalam file yang sama.
LinuxWindowsScript.bat
Ringkasan
Di Linux
Baris pertama (
echo >/dev/null # >nul & GOTO WINDOWS & rem ^
) akan diabaikan dan skrip akan mengalir melalui setiap baris segera setelahnya sampaiexit 0
perintah dijalankan. Setelahexit 0
tercapai, eksekusi skrip akan berakhir, mengabaikan perintah Windows di bawahnya.Di Windows
Baris pertama akan menjalankan
GOTO WINDOWS
perintah, melewati perintah Linux segera setelahnya dan melanjutkan eksekusi pada:WINDOWS
baris tersebut.Menghapus Carriage Returns di Windows
Karena saya mengedit file ini di Windows, saya harus secara sistematis menghapus carriage return (\ r) dari perintah Linux atau saya mendapat hasil yang tidak normal saat menjalankan bagian Bash. Untuk melakukan ini, saya membuka file di Notepad ++ dan melakukan hal berikut:
Mengaktifkan opsi untuk melihat karakter baris (
View
>Show Symbol
>Show End of Line
). Pengembalian kereta kemudian akan ditampilkan sebagaiCR
karakter.Lakukan Find & Replace (
Search
>Replace...
) dan centangExtended (\n, \r, \t, \0, \x...)
opsi.Ketik
\r
diFind what :
bidang dan kosongkanReplace with :
bidang tersebut sehingga tidak ada apa pun di dalamnya.Mulai dari bagian atas file, klik
Replace
tombol sampai semua karakter carriage return (CR
) telah dihapus dari bagian Linux atas. Pastikan untuk meninggalkan karakter carriage return (CR
) untuk bagian Windows.Hasilnya adalah setiap perintah Linux diakhiri hanya dengan feed baris (
LF
) dan setiap perintah Windows diakhiri dengan carriage return dan line feed (CR
LF
).sumber
Saya menggunakan teknik ini untuk membuat file jar yang dapat dijalankan. Karena file jar / zip dimulai di header zip, saya dapat meletakkan skrip universal untuk menjalankan file ini di bagian atas:
@
in sh melontarkan kesalahan yang disalurkan ke/dev/null
dan setelah itu komentar dimulai. Pada cmd pipa/dev/null
gagal karena file tidak dikenali di windows tetapi karena windows tidak mendeteksi#
sebagai komentar kesalahan disalurkan kenul
. Kemudian ia menggema. Karena seluruh baris didahului oleh sebuah@
itu tidak mendapatkan printet pada cmd.::
, yang memulai komentar di cmd, ke noop di sh. Ini memiliki manfaat yang::
tidak me-reset$?
ke0
. Ini menggunakan:;
trik " adalah label".::
dan mereka diabaikan dalam cmd:: exit
skrip sh berakhir dan saya dapat menulis perintah cmdcommand not found
. Anda harus memutuskan sendiri apakah Anda membutuhkannya atau tidak.sumber
Saya membutuhkan ini untuk beberapa skrip instalasi paket Python saya. Sebagian besar hal antara file sh dan bat sama tetapi beberapa hal seperti penanganan kesalahan berbeda. Salah satu cara untuk melakukannya adalah sebagai berikut:
Kemudian Anda menyebutnya dari skrip bash:
File batch Windows terlihat seperti ini:
sumber
Coba proyek BashWin saya di https://github.com/skanga/bashwin yang menggunakan BusyBox untuk sebagian besar perintah Unix
sumber
Ada alat build independen platform seperti Ant atau Maven dengan sintaks xml (berdasarkan Java). Jadi, Anda bisa menulis ulang semua skrip Anda di Ant atau Maven dan menjalankannya meskipun tipe os. Atau Anda bisa membuat skrip Ant wrapper, yang akan menganalisis jenis os dan menjalankan skrip bat atau bash yang sesuai.
sumber