你最初try 的问题是:
find www/*.html -type f -exec sh -c "echo $(basename {})" \;
在执行find
命令之前,$(basename {})
代码执行一次.单个basename
的输出是{}
,因为这是{}
作为文件名的基本名称.因此,find执行的命令是:
sh -c "echo {}"
对于找到的每个文件,但实际上每次都有find
个替换原始(未修改的)文件名,因为要执行的字符串中会出现{}
个字符.
如果你想让它工作,你可以用单引号代替双引号:
find www/*.html -type f -exec sh -c 'echo $(basename {})' \;
然而,让echo
重复到标准输出——basename
无论如何都会写入标准输出——有点毫无意义:
find www/*.html -type f -exec sh -c 'basename {}' \;
当然,我们还可以进一步降低到:
find www/*.html -type f -exec basename {} \;
你能解释一下单引号和双引号的区别吗?
这是常规的shell 行为.让我们略微不同的命令(但只是轻微的-文件的名称可以在www
目录下的任何地方,而不是仅仅一个级别以下),并查看命令的单引号(SQ)和双引号(DQ)版本:
find www -name '*.html' -type f -exec sh -c "echo $(basename {})" \; # DQ
find www -name '*.html' -type f -exec sh -c 'echo $(basename {})' \; # SQ
单引号将包含的material 直接传递给命令.因此,在SQ命令行中,启动find
的shell将删除包含引号的命令,find
命令将其$9
参数视为:
echo $(basename {})
因为shell删除了引号.相比之下,双引号中的material 由shell处理.因此,在DQ命令行中,shell(启动find
的shell,而不是启动by find
的shell)看到字符串的$(basename {})
部分并执行它,返回{}
,因此它传递给find
的字符串作为其$9
参数是:
echo {}
现在,当find
执行-exec
操作时,在这两种情况下,它都会用刚找到的文件名替换{}
(为了便于讨论,www/pics/index.html
).因此,将执行两个不同的命令:
sh -c 'echo $(basename www/pics/index.html)' # SQ
sh -c "echo www/pics/index.html" # DQ
这里有一个(轻微的)符号欺骗——这些是您在shell中键入的等效命令.在这两种情况下,被启动的shell的$2
实际上都没有引号——被启动的shell没有看到任何引号.
如您所见,DQ命令只是简单地 echo 文件名;SQ命令运行basename
命令并捕获其输出,然后 echo 捕获的输出.稍微简化一下,DQ命令可以写成-print
而不是-exec
,SQ命令可以写成-exec basename {} \;
.
如果您使用的是GNUfind
,它支持-printf
操作,后面可以跟Format Directives,因此不需要运行basename
.然而,这只在GNUfind
中可用;这里剩下的讨论适用于你可能遇到的任何版本的find
.