在定位搜索中排除目录

在定位搜索中排除目录

搜索可locate查找文件系统中的路径。
通常,您先验地知道您只对文件或目录感兴趣。
“定位”搜索通常会返回许多结果。在结果中仅包含一种类型会很有用,因为它有助于缩短输出。

但是有一个更有趣的论点可以忽略文件或目录:因为结果路径列表可能不明确 - 不仅在理论上如此。

下面的例子是一个真实的案例,并不罕见:

$ locate --regex --basename "xfce4-keyboard-overlay$"
/usr/local/bin/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay

好的,我们发现了一些东西!但是...文件,还是目录?

$ file /usr/local/bin/xfce4-keyboard-overlay 
/usr/local/bin/xfce4-keyboard-overlay:   bash script

那么这是一个文件...

$ file /usr/local/share/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay: directory

而第二个则不是。

这种歧义使得长长的路径列表难以阅读,因此过滤掉目录真的很好,例如使用locate.

这样的事情存在吗?即使目录过滤器与定位是分开的?

至少,可以使用脚本来迭代所有文件名进行检查 - 这可能会很慢。

答案1

zsh

print -rC1 ${(0)^"$(locate -0 ...)"}(N.)

(0)是一个参数扩展标志,它以 NUL 字符(如我们使用的locate -0)分割,是 的缩写(ps:\0:)

对于^,我们不是(N.)在数组末尾添加,而是将其添加到每个元素。

(N.)是一个 glob 限定符,.仅匹配常规文件,N如果不匹配(不存在或不是常规文件,或者我们无法检查)则删除元素。您还可以使用^/代替来.匹配非目录而不是仅匹配常规文件。或者-.判断文件的类型符号链接解析后(包括匹配中常规文件的符号链接)。

print -rC1打印每个参数生的on 1 Column (与每行写一个相同-l,除了没有任何内容可打印的情况,这种情况在打印一个空行时print -C1不输出任何内容)。print -l

您可以使用任何zsh全局限定符,但请注意订购不会有任何效果,因为我们在这里为每个文件扩展一个 glob,因此每个文件只有一个要排序。

为了更好地识别哪些文件是可执行文件/目录/符号链接/套接字...,您还可以将结果文件作为参数传递以ls -F附加一些*/@=...后缀

这里假设 GNU 工具和类似 Bourne 的 shell:

elocate() {
  locate -0e "$@" |
    sort -z |
    xargs -r0 ls --quoting-style=shell --color=always -Fd1U |
    less -FIXR
}

将定义一个elocate函数,该函数提供 的彩色和分页版本,locate并以 shell 样式引用文件名以避免歧义,并附加后缀以给出类型指示。

答案2

这与其他答案一样不优雅,但效率可能较低:

locate --regex --basename "xfce4-keyboard-overlay$" | 
        while IFS= read -r f; do [ -f "$f" ] && printf "%s\n" "$f"; done

(为了可读性分为两行)。上面将处理包含空格的名称。似乎IFS=有必要处理名称尾随空格,当然,还-r可以让您处理反斜杠。

locate如果存在包含换行符的路径名,“让我们通过管道输入某些内容”的方法可能注定会失败。


有关 的更多信息IFS,请阅读sh(1)或(通过在 *nix 系统中bash(1) 键入man sh或,和/或阅读它man bash这里, 这里, 这里,和/或这里)。然后阅读了解 IFSBash:使用 IFS 逐行读取在 Stack Exchange 上(关注超过 5 票的答案),如果您还没有足够的,请查看Greg Wiki 上的 IFSBash Hackers Wiki 上的 IFS 搜索结果(不在堆栈交换上)。

答案3

xargs-L 1如果您指定或参数,将为每一行重复命令-i

看这里

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i bash -c '(test -d "{}" && echo "{}")'

诚然,它为每个文件启动了一个新的 shell,但它确实具有美观和紧凑的优点。

编辑:我对这个答案不太满意,因为它为每个文件启动了一个新的 shell。这应该只有两个过程:

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i echo 'test -d "{}" && echo "{}"' | bash

当然,如果我们能够完全避免踢解释器就好了,但xargs它链接命令的能力似乎受到了限制。

答案4

我的两分钱:

while IFS= read i; \
do \
  if [ -f "$i" ]; \
  then \
    echo "$i"; \
  fi; \
done < <(locate --regex --basename "xfce4-keyboard-overlay$")

这或多或少是 G-Man 结合流程替代的方式。

相关内容