Saat menggunakan os.system (), sering kali perlu untuk keluar dari nama file dan argumen lain yang diteruskan sebagai parameter ke perintah. Bagaimana saya bisa melakukan ini? Lebih disukai sesuatu yang akan bekerja pada beberapa sistem operasi / shell tetapi khususnya untuk bash.
Saat ini saya melakukan hal berikut, tetapi saya yakin harus ada fungsi pustaka untuk ini, atau setidaknya opsi yang lebih elegan / kuat / efisien:
def sh_escape(s):
return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")
os.system("cat %s | grep something | sort > %s"
% (sh_escape(in_filename),
sh_escape(out_filename)))
Sunting: Saya telah menerima jawaban sederhana menggunakan tanda kutip, tidak tahu mengapa saya tidak memikirkannya; Saya kira karena saya berasal dari Windows di mana 'dan "berperilaku sedikit berbeda.
Mengenai keamanan, saya memahami kekhawatirannya, tetapi, dalam kasus ini, saya tertarik dengan solusi cepat dan mudah yang disediakan os.system (), dan sumber string bukan buatan pengguna atau setidaknya dimasukkan oleh pengguna tepercaya (saya).
sh_escape
Fungsi yang ideal akan keluar dari;
spasi dan dan menghilangkan masalah keamanan hanya dengan membuat file bernama sepertifoo.txt\;\ rm\ -rf\ /
.Jawaban:
Ini yang saya gunakan:
Shell akan selalu menerima nama file yang dikutip dan menghapus kutipan di sekitarnya sebelum meneruskannya ke program yang dimaksud. Khususnya, ini untuk menghindari masalah dengan nama file yang mengandung spasi atau jenis karakter metakarakter cangkang jahat lainnya.
Pembaruan : Jika Anda menggunakan Python 3.3 atau yang lebih baru, gunakan shlex.quote alih-alih menggulung milik Anda sendiri.
sumber
shlex
ataupipes
. Modul python tersebut secara keliru mengasumsikan bahwa karakter khusus adalah satu-satunya hal yang perlu dikutip, yang berarti bahwa kata kunci shell (sepertitime
,case
atauwhile
) akan diurai ketika perilaku itu tidak diharapkan. Untuk alasan itu saya akan merekomendasikan menggunakan rutinitas kutipan tunggal dalam jawaban ini, karena tidak mencoba menjadi "pintar" sehingga tidak memiliki kasus tepi yang konyol.shlex.quote()
melakukan apa yang Anda inginkan sejak python 3.(Gunakan
pipes.quote
untuk mendukung python 2 dan python 3)sumber
commands.mkarg
. Ini juga menambahkan spasi di depan (di luar tanda kutip) yang mungkin diinginkan atau tidak diinginkan. Sangat menarik bagaimana penerapannya sangat berbeda satu sama lain, dan juga jauh lebih rumit daripada jawaban Greg Hewgill.pipes.quote
tidak disebutkan oleh dokumentasi perpustakaan standar untuk modul pipacommand.mkarg
tidak digunakan lagi dan dihapus di 3.x, sementara pipe.quote tetap ada.shlex.quote()
pada 3.3,pipes.quote()
dipertahankan untuk kompatibilitas. [ bugs.python.org/issue9723]Mungkin Anda memiliki alasan khusus untuk menggunakan
os.system()
. Tetapi jika tidak, Anda mungkin harus menggunakansubprocess
modul . Anda dapat menentukan pipa secara langsung dan menghindari penggunaan cangkang.Berikut ini adalah dari PEP324 :
sumber
subprocess
(terutama dengancheck_call
dll) seringkali jauh lebih unggul, tetapi ada beberapa kasus di mana pelolosan shell masih berguna. Yang utama yang saya hadapi adalah ketika saya harus menjalankan perintah ssh remote.Mungkin
subprocess.list2cmdline
tembakan yang lebih baik?sumber
subprocess.list2cmdline(["'",'',"\\",'"'])
memberi' "" \ \"
list2cmdline
sesuai dengan sintaks cmd.exe Windows ( lihat fungsi docstring di kode sumber Python ).shlex.quote
sesuai dengan sintaks shell bourne Unix, namun biasanya tidak diperlukan karena Unix memiliki dukungan yang baik untuk mengirimkan argumen secara langsung. Windows cukup banyak mengharuskan Anda melewatkan satu string dengan semua argumen Anda (dengan demikian kebutuhan untuk melarikan diri yang tepat).Perhatikan bahwa pipe.quote sebenarnya rusak di Python 2.5 dan Python 3.1 dan tidak aman digunakan - Ini tidak menangani argumen panjang-nol.
Lihat masalah Python 7476 ; itu telah diperbaiki dengan Python 2.6 dan 3.2 dan yang lebih baru.
sumber
Perhatikan : Ini adalah jawaban untuk Python 2.7.x.
Menurut sumbernya ,
pipes.quote()
adalah cara untuk " Mengutip string sebagai argumen tunggal untuk / bin / sh ". (Meskipun tidak digunakan lagi sejak versi 2.7 dan akhirnya diekspos secara publik dengan Python 3.3 sebagaishlex.quote()
fungsinya.)Di sisi lain ,
subprocess.list2cmdline()
adalah cara untuk " Menerjemahkan urutan argumen menjadi string baris perintah, menggunakan aturan yang sama seperti runtime MS C ".Inilah kami, platform cara independen mengutip string untuk baris perintah.
Pemakaian:
sumber
Saya percaya bahwa os.system hanya memanggil shell perintah apa pun yang dikonfigurasi untuk pengguna, jadi saya rasa Anda tidak dapat melakukannya dengan cara platform independen. Shell perintah saya bisa apa saja dari bash, emacs, ruby, atau bahkan quake3. Beberapa dari program ini tidak mengharapkan jenis argumen yang Anda berikan kepada mereka dan bahkan jika mereka melakukannya, tidak ada jaminan mereka melakukan pelarian dengan cara yang sama.
sumber
Fungsi yang saya gunakan adalah:
yaitu: Saya selalu menyertakan argumen dalam tanda kutip ganda, dan kemudian tanda kutip mundur satu-satunya karakter khusus di dalam tanda kutip ganda.
sumber
pipes.quote
yang ditunjukkan @JohnWiseman juga rusak. Jadi, jawaban Greg Hewgill adalah yang akan digunakan. (Ini juga yang digunakan shell secara internal untuk kasus biasa.)Jika Anda menggunakan perintah sistem, saya akan mencoba dan memasukkan ke daftar putih apa yang masuk ke panggilan os.system () .. Misalnya ..
Modul subproses adalah pilihan yang lebih baik, dan saya akan merekomendasikan untuk mencoba menghindari penggunaan apa pun seperti os.system / subprocess sedapat mungkin.
sumber
Jawaban sebenarnya adalah: Jangan gunakan
os.system()
sejak awal. Gunakansubprocess.call
sebagai gantinya dan berikan argumen yang tidak lolos.sumber