您最初尝试的问题:
find www/*.html -type f -exec sh -c "echo $(basename {})" \;
是$(basename {})
代码在执行命令之前执行一次find
。单曲的输出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
单引号将包含的材料直接传递给命令。因此,在 SQ 命令行中,启动的 shellfind
删除了封闭的引号,find
命令将其$9
参数视为:
echo $(basename {})
因为外壳删除了引号。相比之下,双引号中的材料是由shell处理的。因此,在 DQ 命令行中,shell(启动find
的——不是由 启动的 find
)看到$(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 中键入的等效命令。在这$2
两种情况下,启动的 shell 实际上都没有引号——启动的 shell 看不到任何引号。
如您所见,DQ 命令只是回显文件名;SQ 命令运行basename
命令并捕获其输出,然后回显捕获的输出。一点还原论的想法表明,DQ 命令可以写成 as-print
而不是 using -exec
,而 SQ 命令可以写成-exec basename {} \;
.
如果您使用的是 GNU find
,它支持格式指令-printf
可以遵循的操作,因此无需运行。但是,这仅在 GNU 中可用;此处讨论的其余部分适用于您可能遇到的任何版本。basename
find
find