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
运行命令的情况,答案缺少要点,这只是一个例子。实际上我可能想在找到的文件上运行而不是-exec
echo
my-command
echo
这是一个可能效率不高但有效的解决方案:
find . -type f -exec sh -c 'echo ${0#./}' "{}" \;
解释:
- 我们依赖于这样一个事实:
sh -c 'echo $0' foobar
运行一个打印 的子 shell$0
,并foobar
作为 传递$0
,因此它打印foobar
- 相反
$0
,我们实际上使用${0#./}
,这意味着“使用$0
,但去掉前导./
(#./
) - 这是参数扩展 - 我们从 exec (找到的带有前导斜杠的
{}
文件名)传递给find
$0
sh -c
所以最后还是my-command
要跑找到没有前导的文件./
,你会这样做:
find . -type f -exec sh -c 'my-command ${0#./}' "{}" \;