答案摘要:虽然文献宣传“-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
简单地打印参数列表(在本例中为文件名)来演示此行为。或者使用-print
which 来执行此操作,而无需调用外部命令。 (注意:-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"' . {} \;