【问题标题】:searching file existence at any depth in bash在bash中搜索任何深度的文件存在
【发布时间】:2016-12-04 01:16:50
【问题描述】:

我需要使用 bash 检查目录中是否存在文件。我试过下面的方法,但它需要完整的路径作为输入。

if [ -e /*/my_file.txt ] ;
then
  echo "file found"
else
  echo "not found"
fi

有什么方法可以动态检查文件是否存在于任何深度。 注意:我不想使用“查找”,因为它需要很多时间来执行。

【问题讨论】:

  • 为什么你认为 Bash 会比 find 快,find 是专门为...“查找”而构建的?
  • 什么是“很多时间”?您的目录中有多少个文件? find 使用了哪些参数?
  • 说我的系统中有 10k 个文件,使用“查找”大约需要 1 分钟以上,这对我来说成本很高。
  • @fedorqui 因为在 bash find '-e' 中,我们需要指定深度以查找文件是否存在。

标签: bash shell file grep find


【解决方案1】:

如果您使用bash 4,您可以编写递归下降层次结构的模式:

shopt -s globstar
for f in /**/myfile.txt; do
    if [[ -e $f ]]; then
        found=1
        echo "File found"
        break
    fi
done
if [[ $found -ne 1 ]]; then
    echo "File not found"
fi

使用find

found=$( find / -name myfile.txt )
if [[ -n $found ]]; then
    echo "File found"
else
    echo "File not found"
fi

【讨论】:

  • if [[ -e "$f" ]],我猜?
  • 如果你愿意,当然可以。不过,没有需要[[ ... ]] 中引用单个参数扩展。
  • 嗯,但是如果文件名包含空格怎么办?我测试了touch "a b"[[ -e a b ]] && echo "yes" 返回错误。
  • [[ ... ]] 内的参数扩展不会进行分词或路径名扩展。这是[[ ... ]](这是一种特殊的bash 构造,与常规命令的处理方式不同)和[ ... ]只是一个常规命令)之间的一个区别。 [[ -e a b ]]f="a b"; [[ -e $f ]] 有很大区别。
  • 啊,对,我不知道这一点。非常有趣,感谢您的解释。
【解决方案2】:

如果您真的关心速度,那么像ls * */* */*/* 这样的文件通配对您没有太大帮助。这个错误有它的限制:参数列表太长。 find 是一个有用的找东西的工具。它非常灵活。但就像使用文件通配一样,它必须在每次调用时扫描目录树。对于偶尔的搜索,例如维护,这是完全可以接受的。但如果这是部分处理流水线,速度是不能接受的。为此,您需要一个优化的数据库。

简单的方法

我知道的大多数 UNIX 都附带locate

如果是预装,可以这样搜索:

$ locate -b '\my_file.txt'

my_file.txt 前面的反斜杠是有意的。它关闭通配符搜索。添加-i 会提供不区分大小写的搜索。

如果该命令不可用,它应该可以从您的操作系统存储库中安装。对于 Debian/Ubuntu:apt install locate。对于第一次初始化,以 root 身份或使用 sudo 运行 /etc/cron.daily/locate

数据库每天更新。对于某些应用程序,此间隔可能太长。通过将 cronjob 从每天更改为每 3 小时点赞一次,您可以获得更新的结果。

实时方式...

这有点超出了这个答案的范围。但是您需要某种守护程序,它会监视内核 inotify 事件以进行目录更改。这些反过来会反映在数据库中,可以通过一些 API 进行查询。就像 MacOS 的 Spotlight 或 Gnome 的 Tracker。

【讨论】:

    【解决方案3】:

    find 是正确的解决方案。

    但是您可以使用 bash 扩展功能

    if ls */* | grep -q my_file.txt
    then echo file found
    else echo file not found
    fi
    

    注意

    • 如果是顶级解决方案,上述解决方案将找不到my_file.txt
    • 如果my_file.txt 是目录名称的一部分,您可能会得到错误的结果。
    • 如果有许多(数千个)目录和许多文件/ 扩展可能会得到粘贴 bash 限制(arg 列表太长)
    • 您可以ls * */* */*/* | grep 使用上述限制状态。

    【讨论】:

    • 感谢 Archemar 的建议。它确实更快的搜索选项来查找文件存在。
    • 使用 ls / | grep -q my_file 我可以看到性能提升。
    猜你喜欢
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多