#避开了shell的空格分割,用引号也有这效果。cao627 写了:看过了看来find命令的作者是考虑到并解决了空格文件名带来的麻烦的代码: 全选
find .... -exec mkdir ....{} \;
书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
- lilydjwg
- 论坛版主
- 帖子: 4258
- 注册时间: 2009-04-11 23:46
- 系统: Arch Linux
- 联系:
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
find 执行的是这样子的(源码未下载;以下是我的推测):cao627 写了:这条命令会这样执行:代码: 全选
mkdir -vp /home/someone/lt/Whitespace Matters
在 /home/someone/lt/目录下创建Whitespace
在当前目录下创建Matters
如果{}只是简单把find找到的内容替换进来,那么我也会在执行find .... -exec mkdir ....{} \;后,在当前目录下生成类似Matters这种由于文件名空格产生的文件
但是没有,说明{}解决了这个问题,而{}是find的一部分,所以 说:“看来find命令的作者是考虑到并解决了空格文件名带来的麻烦的”
[c]
int i;
for(i = 0; strcmp(exec_cmd_args, ";") == 0; i++)
if(strcmp(exec_cmd_args, "{}") == 0)
exec_cmd_args = file_path;
exec_cmd_args = NULL;
execvp(exec_cmd_args[0], exec_cmd_args);
[/c]
所以 find 根本不用管文件名中的空格或者什么其它的东西。对于 C 字符串唯一特别的 NULL 字符不会出现在文件名中。
补充:你可以试试以下代码是否会出问题:
[c]
#include<unistd.h>
int main(int argc, char **argv){
execlp("mkdir", "mkdir", "-p", "some/dir contains whitespace", NULL);
return 0;
}
[/c]
-
- 帖子: 992
- 注册时间: 2007-12-05 10:57
- 系统: ubuntu14.04
- 来自: 金山
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
那个道道是是命令最后的\;吗?自由建客 写了:cao627, 你没理解那个道道
\ 的作用是什么呢?
-exec command {} \; 是find命令的一部分吗? 即离开find命令 -exec command {} \;是否有意义?
-
- 帖子: 1453
- 注册时间: 2008-05-24 8:30
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
-exec command {} \; 是 find 命令的一部分。\ 的作用是防止 shell 对分号进行解释。cao627 写了:那个道道是是命令最后的\;吗?自由建客 写了:cao627, 你没理解那个道道
\ 的作用是什么呢?
-exec command {} \; 是find命令的一部分吗? 即离开find命令 -exec command {} \;是否有意义?
find 并没有刻意去处理文件名中的空格,相反,是 shell 刻意去处理空格,把空格当成参数之间的分隔符,所以才需要加引号。而 find 只是在 -exec 后面遇到 {} 时,把文件名原封不动的传给它调用的命令,而且 {} 对 shell 没有特殊含义,所以从不需要引号。
整个过程是,不管 {} 加不加引号,shell 都把不带引号的 {} 传给 find,然后 find 又把 {} 解释为文件名,换成文件名(不管里面有没有空格、方括号、问号等等对 shell 来说是特殊字符的东西)后,原样传给它启动的命令。
- 自由建客
- 帖子: 13468
- 注册时间: 2008-07-30 23:21
- 系统: Debian stable AMD64
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
剥洋葱一样,只要你明白哪些会被 shell 处理,哪些会被应用程序处理。那个道道是是命令最后的\;吗?
\ 的作用是什么呢?
-exec command {} \; 是find命令的一部分吗? 即离开find命令 -exec command {} \;是否有意义?
末尾的 \; 会被 shell 处理,传给 find 的只有分号。find 就以分号做命令分隔符。
-
- 帖子: 992
- 注册时间: 2007-12-05 10:57
- 系统: ubuntu14.04
- 来自: 金山
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
问题是:然后 find 又把 {} 解释为文件名,换成文件名(不管里面有没有空格、方括号、问号等等对 shell 来说是特殊字符的东西)后,原样传给它启动的命令。
比如
用find命令找到唯一的文件夹/somedir/Whitespace Matters
继续 -exec mkdir /somepath {} \;
然后/somedir/Whitespace Matters会替换掉{}对吗?
然后mkdir命令执行的是 makdir /somepath/somedir/Whitespace Matters对吗
makdir /somepath/somedir/Whitespace Matters 会被shell解析成:
mkdir /somepath/somedir/Whitespace 和 mkdir Matters
即当前目录下莫名其妙被创建个Matters目录
但实验结果是只在/somepath/somedir/下创建’Whitespace Matters‘
如果你用管道把find 的结果传给 mkdir
那么就会在执行这条管道命令的当前目录下创建Matters了
问题是 find ... -exec mkdir /somepath/ {} \; 中Whitespace Matters问题是怎么被解决的?
13楼
应该是在解释这个问题find 并不会调用 shell,而是直接 execv,所以毫无问题
似乎这样理解:
find查找到的内容使用-exec后并不是调用shell 把“表达”打印到屏幕上{}的位置
是经过execv直接把“观念”传给{}的
看来aerofox 也在试图向我说明这点find 并没有刻意去处理文件名中的空格,相反,是 shell 刻意去处理空格,把空格当成参数之间的分隔符,所以才需要加引号。
但没有类比的描述,这个问题对于普通用户确实有点难说清的
谢谢
上次由 cao627 在 2012-03-30 14:54,总共编辑 1 次。
- lilydjwg
- 论坛版主
- 帖子: 4258
- 注册时间: 2009-04-11 23:46
- 系统: Arch Linux
- 联系:
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
你看了我在 17 楼贴的第二段代码没?cao627 写了:
问题是:
比如
用find命令找到唯一的文件夹/somedir/Whitespace Matters
继续 -exec mkdir /somepath {} \;
然后/somedir/Whitespace Matters会替换掉{}对吗?
然后mkdir命令执行的是 makdir /somepath/somedir/Whitespace Matters对吗
makdir /somepath/somedir/Whitespace Matters 会被shell解析成:
mkdir /somepath/somedir/Whitespace 和 mkdir Matters
即当前目录下莫名其妙被创建个Matters目录
但实验结果是只在/somepath/somedir/下创建’Whitespace Matters‘
如果你用管道把find 的结果传给 mkdir
那么就会在执行这条管道命令的当前目录下创建Matters了
问题是 find ... -exec mkdir /somepath/ {} \; 中Whitespace Matters问题是怎么被解决的?
13楼应该是在解释这个问题find 并不会调用 shell,而是直接 execv,所以毫无问题
似乎这样理解:
find查找到的内容使用-exec后并不是调用shell 把“表达”打印到屏幕上{}的位置
是经过execv直接把“观念”传给{}的
-
- 帖子: 992
- 注册时间: 2007-12-05 10:57
- 系统: ubuntu14.04
- 来自: 金山
Re: 书上学到的一条命令,将一个目录下的目录树,创建到另一个目录下,但有点不解。
恩懂了你看了我在 17 楼贴的第二段代码没?
mkdir /Whitespace Mattersmkdir 并没有刻意去处理文件名中的空格,相反,是 shell 刻意去处理空格,把空格当成参数之间的分隔符,
是shell解释这条命令将Whitespace Matters中的空格做分割符了
而在find ... -exec mkdir {} \; (如果find ... 查找的结果是/Whitespace Matters)
执行mkdir时 shell已经不再介入,去误导mkdir “你先去/下创建Whitespace 然后再在当前目录创建Matters”
mkdir只是安安静静在执行它的本质 execlp("mkdir", "mkdir", "-p", "findout", NULL);