findコマンドってのも、FreeBSD、Solaris、Linuxの何か等、OSごとに「方言」がきついコマンドの1つですよね。OSごとに、オプションがあったりなかったりすることは、よくあります。
いざとなれば、GNUのfindutilsをインストールすれば、違いを吸収できたりしますが…。
さてさて、FreeBSDのfindコマンドには、-deleteという、ファイルを削除してくれるオプションがあります。「-exec rm {} \;」と書かなくてすむので、いくらか便利かな、みたいなものですが。
しばらく前から気になってたんですが、
find: -delete: /tmp/ttt: relative path potentially not safe
というようなメッセージが表示されることがあります。
実例をあげます。
たとえば、以下のようなお膳立てをしておきます。
cd /tmp
mkdir ttt
mkdir ttt/uuu
mkdir ttt/uuu/vvv
touch ttt/uuu/vvv/www.txt
touch ttt/uuu/vvv/xxx.txt
touch ttt/uuu/vvv/yyy.txt
そのあと、あまり実用的でない、無意味な実行例ですが、「find /tmp/ttt -print -delete」を実行します。
% find /tmp/ttt -print -delete
/tmp/ttt/uuu/vvv/www.txt
/tmp/ttt/uuu/vvv/xxx.txt
/tmp/ttt/uuu/vvv/yyy.txt
/tmp/ttt/uuu/vvv
/tmp/ttt/uuu
/tmp/ttt
find: -delete: /tmp/ttt: relative path potentially not safe
「relative path potentially not safe」がでますね。
そして結局、/tmp/tttというディレクトリは削除されずに残ります。
% ls -lRa /tmp/ttt
total 6
drwxr-xr-x 2 ttt wheel 512 4 15 22:37 ./
drwxrwxrwt 10 root wheel 3072 4 15 22:37 ../
ちなみに、以上は、FreeBSD 7.0-RELEASEで実行した結果です。
findコマンドのマニュアルを読んでみますか。
-delete
Delete found files and/or directories. Always returns true.
This executes from the current working directory as find recurses
down the tree. It will not attempt to delete a filename with a
``/'' character in its pathname relative to ``.'' for security
reasons. Depth-first traversal processing is implied by this
option.
なるほど。でも、ここの意味
a filename with a ``/'' character in its pathname relative to ``.''
なんか微妙というか、あいまいな気がしません?
/tmp/ttt だったら、relativeじゃなくて、absolute pathじゃないか…って。
わからないことがあったら、ソースコードを確認。
の、この部分ですね。
/*
* -delete functions --
*
* True always. Makes its best shot and continues on regardless.
*/
int
f_delete(PLAN *plan __unused, FTSENT *entry)
{
/* ignore these from fts */
if (strcmp(entry->fts_accpath, ".") == 0 ||
strcmp(entry->fts_accpath, "..") == 0)
return 1;
/* sanity check */
if (isdepth == 0 || /* depth off */
(ftsoptions & FTS_NOSTAT) || /* not stat()ing */
!(ftsoptions & FTS_PHYSICAL) || /* physical off */
(ftsoptions & FTS_LOGICAL)) /* or finally, logical on */
errx(1, "-delete: insecure options got turned on");
/* Potentially unsafe - do not accept relative paths whatsoever */
if (strchr(entry->fts_accpath, '/') != NULL)
errx(1, "-delete: %s: relative path potentially not safe",
entry->fts_accpath);
strchr(entry->fts_accpath, '/') で判断しているので、“/”が含まれているときはエラー扱いになるようで。
manに書いてある“.”なんてのは関係なくて、directory tree内をtraverseしていって 、降りていったディレクトリをカレントディレクトリとみなして、そこからの相対パスで、というか、ディレクトリ名をまったくつけない(/を含まない)、ファイル名だけが、entry->fts_accpathに入ってるっぽいです。ふつうは。
ただし、findの起点を/tmp/tttのように絶対パスで指定すると、最後の最後で、entry->fts_accpathには、起点の/tmp/tttが、そのまま代入されてしまうみたいで、
find: -delete: /tmp/ttt: relative path potentially not safe
となっていた、というわけですか。
じゃあ、どうすればいいかっていうと、起点を/tmp/tttのような絶対パス指定しなければいいというわけで、正解は「find ttt -print -delete」になるんでしょうね。
% cd /tmp
% find ttt -print -delete
ttt/uuu/vvv/www.txt
ttt/uuu/vvv/xxx.txt
ttt/uuu/vvv/yyy.txt
ttt/uuu/vvv
ttt/uuu
ttt
% ls -ld ttt
ls: ttt: No such file or directory
ただ、起点となるディレクトリは消えて欲しくない、っていう場合もあったりしまして~、実は私のやりたかったことが、まさにそれでして、たまたま結果オーライで、「find /tmp/ttt ...」でうまくいってたのでした。
0 件のコメント:
コメントを投稿