与 -exec echo {} 选项一起使用时从 find 命令输出中删除前导点

与 -exec echo {} 选项一起使用时从 find 命令输出中删除前导点
find . -type f -exec  echo {} \;

使用上面的命令,我想获取不带前导“./”字符的文件名。基本上,我想得到:

filename

代替:

./filename

有办法做到这一点吗?

答案1

使用*代替.,行距./就会消失。

find * -type f

请注意,shell 首先将其扩展*为当前工作目录中非隐藏(默认)文件的排序列表,并将它们传递.find.这有几个值得注意的含义:

  • 隐藏文件在顶层被省略,但在更深层次(由 遍历的文件find)不会被省略。
  • 该列表在顶层排序(通常是一个加号)
  • 如果当前工作目录有很多文件,您可能会遇到可传递给命令的参数数量限制。
  • !如果存在名为、或名称以 开头的文件,则该方法将不起作用,如果存在名为 的文件,则可能会产生严重(后果。)--delete

答案2

假设您不想要单独的文件名,还需要不带前导的完整相对路径./,如果您有 GNU,find则可以使用:

find . -type f -printf '%P\n'

从 find(1) 手册页:

%P- 文件名以及发现该文件的起点名称已被删除。

否则,您可以尝试以下其中一项:

find . -type f -print | cut -d/ -f2-

find .[!.]* * -type f -print

您应该避免最后一个(如果您的目录中有很多条目,请考虑过长的命令行)。

-print与您的功能相同,-exec echo {} \;但更好:没有外部进程调用,因此开销较低,并且文件名以破折号开头没有不良副作用。

答案3

find . -type f -exec echo {} \;

默认操作find是打印结果。如果没有明确告知,find则默认搜索当前目录。您的命令可以简化为find -type f.

为什么/什么时候这很重要?只有当您在足够大的目录上运行此命令时,您才会开始看到性能差异。-exec echo {} \;将使您的计算机不必要地工作更多,因为它必须启动一个外部进程,例如/bin/echo打印文件名。 echo 可执行文件的一个实例针对 找到的每个文件运行find

要回答有关删除的问题./,更有效的方法是使用cut.您知道前两个字符始终是./cut -c3-只会保留位置 3 及以后的字符。

> cd /etc/fonts/conf.d
> find -type f | cut -c3-
99pdftoopvp.conf
00kde.conf
65-khmer.conf
README

如果您的文件名包含换行符,这将无法按预期工作,但这是另一个全新的故事。

答案4

对于我想通过参数printf运行命令的情况,答案缺少要点,这只是一个例子。实际上我可能想在找到的文件上运行而不是-execechomy-commandecho

这是一个可能效率不高但有效的解决方案:

find . -type f -exec sh -c 'echo ${0#./}' "{}" \;

解释:

  • 我们依赖于这样一个事实:sh -c 'echo $0' foobar运行一个打印 的子 shell $0,并foobar作为 传递$0,因此它打印foobar
  • 相反$0,我们实际上使用${0#./},这意味着“使用$0,但去掉前导./( #./) - 这是参数扩展
  • 我们从 exec (找到的带有前导斜杠的{}文件名)传递给find$0sh -c

所以最后还是my-command要跑找到没有前导的文件./,你会这样做:

find . -type f -exec sh -c 'my-command ${0#./}' "{}" \;

相关内容