コマンド
$ find ~/foo/ -type f -iname "*.txt" -print0 | parallel -0 cat
GNU Parallel を使用して、.txt
の下のすべての~/foo/
ファイルを印刷します。
pythonスクリプトがあり、このbashコマンドを呼び出します:
import subprocess, sys
def runBashCommand(my_command):
process = subprocess.Popen(my_command.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
return None
def makeCommand(my_path):
return "find {} -type f -iname \"*.txt\" -print0 | parallel -0 cat".format(my_path)
発行中
>>> makeCommand('~/foo/')
戻り値
'find ~/foo/ -type f -iname "*.txt" -print0 | parallel -0 cat'
しかし発行
>>> runBashCommand(makeCommand('~/foo/'))
エラーが発生します
find: paths must precede expression: |
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
スクリプトの何が問題になっていますか?
実際にはbash
コマンドを実行していません。あなたがしていることは、実行可能ファイルを直接実行し、それに引数を渡すことです。
次のスクリプトを試して、何が起こっているかを確認してください。
_import subprocess
p = subprocess.Popen(["echo", "a", "b", "|", "rev"], stdout=subprocess.PIPE)
print p.communicate()
_
出力は次のようになります。
_('a b | rev\n', None)
_
リダイレクトは発生していません。「|」文字通り渡されています。つまり、_find ... \| parallel ...
_と入力した場合と同じです。したがって、エラー。
修正するには2つの方法があります。
簡単な方法:_Shell=True
_を_subprocess.Popen
_に渡します。これにより、必要なものがすべてシェルを介して実行されます。その場合、配列ではなく文字列を渡す必要もあります。
_import subprocess
p = subprocess.Popen("echo a b | rev", stdout=subprocess.PIPE, Shell=True)
print p.communicate()
# Result: ('b a\n', None)
_
これを行う場合は、文字列への引数の置換に十分注意してください。
強力な方法:Pythonを使用して2つのプロセスを開き、それらを一緒にパイプします。
_import subprocess
# First command
p1 = subprocess.Popen(["echo", "a", "b"], stdout=subprocess.PIPE)
# Second command's input linked to the first one's output
p2 = subprocess.Popen(["rev"], stdin=p1.stdout, stdout=subprocess.PIPE)
# Read from p2 to get the output
print p2.communicate()
# Result: ('b a\n', None)
_
これはより堅牢で、余分なシェルを生成しませんが、一方ではよりタイピングします。これを行うと、noシェル置換が発生することに注意してください。あなたの場合、それはあなたがそれを必要としているようには見えませんが、もしあなたが例えば_~
_を使いたいなら、あなたはそれをPython(eg os.getenv("HOME")
)。
コマンド文字列には、_~
_や_|
_などのシェルで処理する必要のある文字が含まれているため、split()
することはできません。バージョンを使用:
_process = subprocess.Popen(my_command, stdout=subprocess.PIPE, Shell=True)
_