phpのsystem関数の中の変数の扱い

 rsyncの--excludeオプションがphpスクリプトの中で効かない。どうもsystem関数の動きがおかしそう。で、こんなスクリプトを作ってみた。

<?php
error_reporting(E_ALL);
$str = "--exclude={'*.wav','*.mp3','log/','*.img','log/'}";

system("echo $str\n");
passthru("echo $str\n");
echo (exec("echo $str\n"));echo "\n";
echo `echo $str`;
echo "$str\n";
?>

 実行結果。

 やはりrsyncの--excludeがうまくいかないのはここか。外部プログラムを実行する際にはコーテーションが取り除かれると。シングルコーテーションとダブルコーテーションを入れ替えてもやはりコーテーションが取り除かれる。
 一部エスケープしてみた。

<?php
error_reporting(E_ALL);
$str = "--exclude={\'*.wav\','*.mp3','*.log','*.img','log/'}";

system("echo $str\n");
passthru("echo $str\n");
echo (exec("echo $str\n"));echo "\n";
echo `echo $str`;
echo "$str\n";
?>

 実行結果。

 とりあえずエスケープしたら通りそう。
 replaceしてみる。

<?php
error_reporting(E_ALL);
$str = str_replace("'","\'","--exclude={'*.wav','*.mp3','*.log','*.img','log/'}");

system("echo $str\n");
passthru("echo $str\n");
echo (exec("echo $str\n"));echo "\n";
echo `echo $str`;
echo "$str\n";
?>

 実行結果。

 これでええか。

 でもなんでこんな仕様なんやろ?セキュリティ対策?とりあえずescapeshellargという関数があることにたどり着いた。

<?php
error_reporting(E_ALL);
$str = escapeshellarg("--exclude={'*.wav','*.mp3','*.log','*.img','log/'}");

system("echo $str\n");
passthru("echo $str\n");
echo (exec("echo $str\n"));echo "\n";
echo `echo $str`;
echo "$str\n";
?>

 実行結果。

 addslashesという関数もある。ソースコード省略。こちらのほうが元の変数の変わりようが自然なのでは。