搜索可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
C
olumn (与每行写一个相同-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
这里,
这里,
这里,和/或这里)。然后阅读了解 IFS
和Bash:使用 IFS 逐行读取在 Stack Exchange 上(关注超过 5 票的答案),如果您还没有足够的,请查看Greg Wiki 上的 IFS
和Bash 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 结合流程替代的方式。