在查找搜索中排除目录


13

搜索带有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

而第二个则不是。

这种歧义使得一长串的路径难以阅读,因此最好将目录过滤掉,例如使用的comman行选项locate

是否存在这样的东西?即使目录过滤器与locate分开?

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

Answers:


3

zsh

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

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

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

(N.)是glob限定符,.仅匹配常规文件,N如果不匹配则删除该元素(不存在或不是常规文件,或者我们无法检查)。您还可以使用^/而不是.匹配非目录,而不是仅匹配常规文件。

print -rl将每个参数原始打印在单独的行上

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

(请注意,如果报告的最后一个文件locate以换行符结尾(所有shell中都存在命令替换错误功能),则可能会失败)。


3

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

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)bash(1) (通过在* nix系统中键入man shman bash/和/或在此处此处此处和/或此处阅读)。然后阅读《了解IFSBash:逐行阅读》,在Stack Exchange上使用IFS(着重于5票以上的答案),如果还不够,请在Greg的WikiIFS搜索结果查看IFS。在Bash Hackers Wiki上(不在Stack Exchange上)。


您可以在while语句后添加有关“ IFS =“的内容的信息吗?
罗伯特

我已经做到了
G-Man说'Restore

对于许多echo实现,反斜杠仍然是一个问题。您应该使用printf任意数据
斯特凡Chazelas

有可能是你的换行符问题的解决方案,通过使用“--null”参数locate和增强您read的建议在这里transnum.blogspot.ie/2008/11/...
罗伯特

@StéphaneChazelas:好点。固定。
G-Man说'恢复莫妮卡'

2
locate --null --regex --basename "xfce4-keyboard-overlay$" |
  xargs -r0 sh -c 'find "$@" -prune ! -type d' sh

实际上,它甚至比看起来还脏...但是很好。让我们假装它是伪代码,那么它会很有帮助:)
Volker Siegel 2015年

1
@Volker:我同意这很不好:在您的示例中,它将列出列表/usr/local/share/xfce4-keyboard-overlay 及其每个子目录。添加-maxdepth 0帮助。
G-Man说'恢复莫妮卡'

甚至更好...:D locate --regex --basename "xfce4-keyboard-overlay$" | xargs -I % sh -c "test -d % && echo %"
FloHimself 2015年

1
使用xargswith find是个好主意,我对其进行了编辑以使其更强大。希望你不要介意。
斯特凡Chazelas

1

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似乎束缚了其链接命令的能力。


3
那只是重新启动了我的机器(有一个名为的文件/home/evil/$(reboot)/xfce4-keyboard-overlay,我愚蠢地将其作为来运行root)。
斯特凡Chazelas

2
@StéphaneChazelas+1为勇气以root身份运行“来自互联网的随机编解码器”;)(scnr)
Volker Siegel

0

我的两分钱:

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

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


实际上,这或多或少是做的方法,再加上进程替换,减去了处理包含反斜杠或尾随空格的文件名的能力。另外,请注意,问题标题显示为“排除目录”,并且此答案仅包含目录。
G-Man说'恢复莫妮卡'

抱歉。我的错。已更正。
Tristan Storch 2015年

-1

如果locatefile和结合使用该grep怎么办?...

$ for f in `locate --regex --basename "xfce4-keyboard-overlay$"`; do file $f; done | grep -vi directory

我没有进行测试,但是我认为这可能会很慢,因为它会file为每个路径创建一个过程。请注意,通常有很多行要查找的结果。我当前的测试正在搜索“ gnome”,给出了大约73000条测试路径。
Volker Siegel

2
@Volker:比这更糟:对于$f文件中的每个文件,file程序都会打开该文件并从中读取文件。当您需要做的只是一个时,这是非常昂贵的stat()。………………此外,这对于名称中包含“目录”的文件(例如“ phone_directory”)也会产生错误的结果。…………(而且,for f in `…`; do …语法不能处理包含空格的名称。)
G-Man说'Reinstate Monica'15
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.