【问题标题】:Display files matching a term recursively but don't descend into matching directories以递归方式显示与术语匹配的文件,但不下降到匹配的目录
【发布时间】:2021-06-24 00:42:27
【问题描述】:

我正在尝试编写一个 bash 脚本,用于在整个计算机(不包括系统文件和 Homebrew 文件)中搜索包含(其文件名)给定术语 ($1) 的文件和文件夹。但是,如果一个文件夹已添加到结果列表中并且它包含子文件夹/文件(它们的文件名再次)包含搜索词,那么我不想添加子文件夹/文件。

这是我试图获得的输出示例:

"/Users/example/Library/Logs/Brave"
"/Users/example/Library/Application Scripts/com.brave.desktop"
"/Users/example/Library/Application Scripts/com.brave.desktop.safari"
"/Users/example/Library/Containers/com.brave.desktop.safari"
# not this last one
"/Users/example/Library/Containers/com.brave.desktop.safari/Data/Library/Application Scripts/com.brave.desktop.safari"

为了提供一些上下文,脚本的输出将用于删除文件/文件夹,这就是我不想输出子文件夹的原因。

到目前为止,这是我的脚本:

searchResults=($(fd --exclude /System --exclude /usr/local/Homebrew -uu $1 / | sed -e 's/^/"/g' -e 's/$/"/g' | tr '\n' ' '))

for res in "${searchResults[@]}"
do
    printf '%s\n' $res
done

示例 查询词语:搅拌机 假设我的电脑有这些文件和文件夹:

"/Users/example/Library/Logs/blender"
"/Users/example/Library/Application Scripts/com.blender.desktop"
"/Users/example/Library/Application Scripts/com.blender.desktop/blenderfile.txt"
"/Users/example/Library/Application Scripts/com.blender.desktop/blenderfolder"

脚本应该输出:

"/Users/example/Library/Logs/blender"
"/Users/example/Library/Application Scripts/com.blender.desktop"

我没有太多关于 bash 脚本的知识,所以我不知道该怎么做。任何想法将不胜感激。

【问题讨论】:

  • @oguzismail 我添加了一个示例以进行澄清。本质上,因为我将使用搜索结果删除来删除文件/文件夹,例如 /something 和 /something/example.txt 出现在搜索结果中,我将删除 /something 然后 /something/example.txt这会破坏脚本,因为它已经被删除了。
  • 是的,这就是我想要实现的目标。

标签: bash macos sed


【解决方案1】:

使用传统的find,您可以执行以下操作来列出名称中包含搜索词的文件,但那些位于已找到目录中的文件除外。

#/bin/sh -
find '/' \
  ! \( -path '/System' -prune \) \
  ! \( -path '/usr/local/Homebrew' -prune \) \
  -name "*$1*" -prune

您无需进一步处理其输出。如果您将-exec rm -rf {} + 附加到它,则这些文件将被删除,无论它们的名称是否包含异常字符。

我不知道是否有更简单的方法使用 fd

【讨论】:

    【解决方案2】:

    我认为使用 sed(您已标记)会发现的主要问题是 sed 进行贪婪匹配。例如

    search="repos" 
    results=$(find | sed -n "s/\(.*$search\).*/\1/p" | uniq)
    

    幸运的是 perl 允许非贪婪匹配,您可以使用它来过滤掉包含多次搜索字符串的结果。

    search="repos"
    results=$(find | sed -n "s/\(.*$search\).*/\1/p" | perl -pe "s/(.*?$search).*/\1/" | uniq)
    

    我没有要测试的 MacOS 系统,但我相信这应该可以。 (请注意,如果您愿意,可以使用 fd 而不是 find)我没有包含排除这些目录的逻辑,因为您似乎已经对这些目录进行了排序。

    编辑: 刚刚意识到我的代码可能会切断文件或目录名称的结尾。这是固定版本,它也使用您原来的 fd 命令

    search="repos"
    results=$(fd --exclude /System --exclude /usr/local/Homebrew -uu $search | perl -pe "s/(.*?$search.*?\/|$).*/\1/i;s/\/$//" | uniq)
    

    【讨论】:

    • 这是一个好的开始,谢谢!但是它会修剪结果。我有这个文件:/Users/example/Library/Caches/com.repos.desktop.ShipIt,脚本输出/Users/example/Library/Caches/com.repos
    • 是的,我一发布就注意到,我已经更新了我的答案。
    猜你喜欢
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 2014-05-02
    相关资源
    最近更新 更多