我想 echo linux命令行上查找的文件名部分.我try 使用以下方法:

find www/*.html -type f -exec sh -c "echo $(basename {})" \;

find www/*.html -type f -exec sh -c "echo `basename {}`" \;

和 a whole host of other combinations of escaping 和 quoting various parts of the text. The result is that the path isn't stripped:

www/channel.html
www/definition.html
www/empty.html
www/index.html
www/privacypolicy.html

为什么不呢?

更新:虽然我下面有一个可行的解决方案,但我仍然对为什么"basename"没有做到它应该做的事情感兴趣.

推荐答案

你最初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.

Linux相关问答推荐

使用Bash从文件名中删除日期名称

是否可以在Bash正则表达式中排除?

pci_user_write_config_word在哪里实现?

我可以在不调用 shell 的情况下使用 popen() 吗?在 C++ 中

在 cURL 中使用的确切位置将字节分成一些范围部分

awk内部的变量操作

另一个远程的 Git 合并分支

在 Bash 中识别接收到的信号名称

将 awk 输出保存到变量

size_t 和 off_t 的用法有什么区别?

nvm:无法卸载当前活动的 node 版本

Linux:在目录下的文件列表中搜索特定单词

用于数据库备份的 Linux shell 脚本

to_string不是std的成员?

如何在 Linux 上传递带感叹号的参数?

当将信号量减为零的进程崩溃时,如何恢复信号量?

事件驱动和异步有什么区别?在 epoll 和 AIO 之间?

更改 /etc/profile 后,我需要做什么来重置我的 shell?

仅当文件存在于 shell 脚本中时才移动

如何在 docker 容器中运行 cron 作业(job)