を使って多くのファイルを作成しようとしていますC
。私は終わったmkdir -p directory && touch directory/filename
。私のループが名前に特殊文字を含むファイルに到達するとエラーが発生します。
syntax error :" unexpected "("
助けてください?
答え1
あなたの問題system()
はsystem()
。これはまた、結果シェルが独自の構文を使用してコマンド全体を評価するため、シェルが特別に処理する文字をエスケープする必要があることを意味します。
Cでファイルとディレクトリを生成するより強力でエラーの少ない方法は、この操作に提供される実際のC関数、つまりおよびmkdir()
/open()
を使用することですcreat()
。
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int
main(void)
{
char dir[] = "some(directory)with*special[characters]";
char file[] = "some(file)with*the[same]characters";
int fd;
if (mkdir(dir, 0755) == -1)
err(EXIT_FAILURE, "creating directory failed");
if ((fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
err(EXIT_FAILURE, "creating file failed");
close(fd);
/* ... */
return 0;
}
答え2
次のようにファイルパスを引用符で囲みます。
touch "directory/file"
答え3
ファイル名を「引用」する必要があります。
touch "directory/file with whitespace (and special characters)"
引用と特殊文字についてはbashのマニュアルを読んでください。
答え4
system()
パラメータを含むシェルコマンドを呼び出すためにinsideを使用する場合は、これらのパラメータを引用しないようにC
環境を使用してパラメータを渡すことをお勧めします。
ファイルパス(文字を含む)は次の場所に保存されますfile_path
。
if (setenv("FILE", file_path, 1) < 0) {
perror("setenv");
exit(1);
}
system("mkdir -p -- \"$(dirname -- \"$FILE\")\" && touch -- \"$FILE\"");
これにより(内部で呼び出された)固定文字列を渡すことができ、sh -c
シェルコードが正しい場合(上記の引用符を参照)、任意のsystem()
コード注入の脆弱性について心配する必要はありません。--
sh
(上記には、すべての末尾の改行が削除される一般的なコマンド置換の問題があるため、file_path
同様の状況では失敗しますfoo/bar\n/file
。これを行うかどうかを判断します)。
シェルコードのファイル名を渡すsystem()
場合いいえする:
sprintf(cmd, "mkdir -p -- \"%s\" && touch -- \"%s\"", dir_path, file_path);
これは依然としてコマンドインジェクションの脆弱性であるためです(例:ファイル名は、または$(reboot)
のようなものです。";reboot;:"
二重引用符ではなく一重引用符を使用している場合も同様です。
以下を行う必要があります。
sprintf(cmd, "mkdir -p -- %s && touch -- %s",
shquote(dir_path), shquote(file_path));
各文字を一重引用符で置き換え、結果を囲むshquote()
関数(実装は練習のまま)はどこにありますか?したがって、たとえばreturn for(参照ファイルは最大4 *長さ+ 2になる可能性があるため、バッファにスペースを割り当てるときに考慮する必要があります)。'
'\''
'foo'\''bar'
foo'bar
cmd
これが最も安全な参照方法です。二重引用符やバックスラッシュを使用する引用方法は、外部文字セットを使用する一部のロケールで問題になり、潜在的に任意のコード挿入の脆弱性を引き起こす可能性があります。