使用“find”,如何让“rm”打印比通过“-execdir”执行时更完整的路径名?

使用“find”,如何让“rm”打印比通过“-execdir”执行时更完整的路径名?

答案摘要:虽然文献宣传“-execdir”比“-exec”更安全,但不要忽视操作差异。前者并不是后者的简单重新实现。此外,当专门使用 find 进行交互式删除时,通过“-okdir”选项执行“rm -f”也是可行的。对于稍微复杂的结构也是如此。

我正在尝试学习“查找”命令,但无法理解其输出。如果这是重复的,我深表歉意,但问题陈述有点复杂,很难用谷歌搜索。

让我设置一个宠物箱:我从某个目录(“.”)开始,有两个子目录“A”和“B”。在这两个文件中,都有一个名为“hello.c”的文件。

所以,举例来说,

find . -name "hello.c"

会像这样打印:

./A/hello.c
./B/hello.c 

到目前为止,一切都很好。当我尝试使用“-execdir”选项执行某些操作时,我会迷失方向;假设我想使用交互式删除。然后:

find . -name "hello.c" -execdir rm -i {} \;

或类似的。我期望的是

rm: remove regular file "./A/hello.c"?

然后,回答这个问题,在目录“B”中出现类似的“hello.c”提示。不幸的是,实际出现的是

rm: remove regular file "./hello.c"? 

在这个小例子中,我可以合理地推断它正在询问“./A/hello.c”,但如果扩大这个例子,那么你会得到几十个文件,它们的路径名都被截断为“./”。我无法区分数十个“./hello.c”,这与它们各自所在的子目录有关。

所以,我的问题归结为希望通过“-execdir”打印更完整的路径名。我能听到一些提示,说明我没有注意到联机帮助页中的哪些微妙之处吗?关于“{}”替换的内容很少提及。或者,如果有更好的方法来管理这种特殊情况(交互式删除),我也想听听,因为我不确定我的方法是最佳实践。

答案1

GNU 的手册页部分find描述如下:-execdir

与 类似-exec,但指定的命令是从包含匹配文件的子目录运行的,该子目录通常不是您启动的目录find

所以不涉及真正的微妙之处。-exec从运行的目录调用命令find(因此需要提供相对于该目录的路径或从根目录开始的绝对路径),并-execdir从包含文件的目录调用命令,因此不需要提供完整的路径路径,所以没有。

为了获得您想要的行为,您应该使用-exec而不是-execdir.

您可以通过将rm调用替换为echo简单地打印参数列表(在本例中为文件名)来演示此行为。或者使用-printwhich 来执行此操作,而无需调用外部命令。 (注意:-print如果没有给出,这也是默认操作。)

如果您不需要确认,-delete则可以使用。对于大量文件,这也可能更有效,因为它避免了rm一次又一次的调用。

答案2

为了获得安全优势-execdir(这实际上是为了确保命令不会获取包含多个组件的路径)并获得提示,您可以使用:

find . -name hello.c -okdir rm -f {} \;

(请注意,至少 GNU 实现find不会像 GNU 那样以适合终端的方式转义文件名rm(wrt 控制、换行符、不可打印字符...))。

答案3

-exec您可以只打印工作目录,而不是使用更简单但安全性较低的 。例如

-execdir sh -c 'pwd ; rm -i "$1"' . {} \;

或者,打印整个路径

-execdir sh -c 'readlink -e "$1" ; rm -i "$1"' . {} \;

相关内容