【问题标题】:Check if a directory that meets a certain criteria exists in bash检查bash中是否存在满足一定条件的目录
【发布时间】:2018-10-10 02:29:15
【问题描述】:

我正在尝试让 bash 检查目录是否存在,但前提是它满足特定条件。

例如,我想检查一个以pkg_ 开头的目录是否存在,后面有任何其他字符。

因此,如果存在名为 pkg_1.0pkg_2.0 的文件夹,bash 仍然会捕获它。

目前代码如下所示:

if [ -d "~/pkg_*" ];

但每次运行时,无论是否存在任何请求pkg_的目录,它都会返回false

同时,使用cd ~/pkg_* 工作得很好,我可以cd 进入该目录。

【问题讨论】:

    标签: bash shell directory


    【解决方案1】:
    shopt -s nullglob
    for path in ~/pkg_*/
    do
        [do what you want if at least one such directory exists]
        break
    done
    

    解释:

    • 设置nullglob可确保~/pkg_*/在不存在此类目录时解析为空字符串,这意味着我们不会进入循环。
    • 尾部斜杠确保我们只匹配目录,而不是普通文件。
    • expand tilde and asterisk 您希望这些字符需要不加引号。如果quoted 这些匹配文字文件名中的波浪号和星号字符,这是可能的,但非常不寻常。
    • break 停止循环,因此条件只运行一次。

    示例会话:

    $ cd
    $ shopt -s nullglob
    $ for path in ~/pkg_*/
    > do
    >     echo 'Found one!'
    >     break
    > done
    $ mkdir 'pkg_a'
    $ for path in ~/pkg_*/
    > do
    >     echo 'Found one!'
    >     break
    > done
    Found one!
    $ mkdir 'pkg_b with spaces'
    $ for path in ~/pkg_*/
    > do
    >     echo 'Found one!'
    >     break
    > done
    Found one!
    

    【讨论】:

      【解决方案2】:

      虽然不是优雅的单线,但您可以试试这个:

      filelist="$HOME/pkg_*"
      for f in $filelist; do
          if [ -d "$f" ]; then
              action_if_true
          fi
      done
      

      但是,如果您有多个匹配的文件夹,这确实会产生多次执行操作的副作用。

      顺便说一句,我使用环境变量 $HOME 代替了第一行中的波浪号,因为波浪号不起作用。

      我对此进行了测试,它似乎也可以在经典的 Bourne shell 中工作。

      那里的 bash 专家可能有更好的答案。

      【讨论】:

      • @l0b0 我想知道我错过了什么。这对我有用,除了我直接提到的多场比赛。你指的是这个吗?
      • 知道了。文件或目录名称中的空格导致它失败。但是在 "$f" 周围添加一个简单的引号就可以解决这个问题。是的,那么它仍然会匹配多个文件夹。这取决于确切的意图。 OP 没有说明是否可以接受多个匹配项。
      【解决方案3】:

      你可以这样做。

      #!/bin/bash
      
          fpath=`find ~/ -type d -name "pkg_*"` #which finds all folder start the name pkg_ in the path ~/
      

      对每个文件夹执行单独的操作

      for fnd in $fpath
      do
          echo "$fnd"
      done
      

      要在不同的路径中搜索,请随意替换~/

      编辑:如果文件夹名称包含空格,请使用此

      #!/bin/bash
        find . -type d | while read fpath; do echo $fpath; done  
      

      【讨论】:

      • 这行不通。如果有多个匹配项,它将运行不止一次,并且文件名中的空格和层次结构更深的pkg_* 文件会做坏事。
      • @l0b0 你测试了吗?
      • @l0b0 让我看看你试图否定的例子。
      • 是的,我确实测试过。当find 找到两个目录时,它运行了两次。
      • 他没有提到它只是路径中的一个目录。我的解决方案是通用的?
      【解决方案4】:

      我真的取决于您需要在哪里查找目录。如果您只需要检查单个目录中是否有 pkg_... 命名的目录,那么您可以使用 for 循环,循环遍历给定目录中的目录,正如 IObO 在他的回答中指出的那样。

      如果您需要在给定目录下的所有子目录中搜索名为pkg_... 的目录,那么使用find 提供了一个方便的选项。在 bash 中,您可以使用 进程替换 将与您的条件匹配的目录名称提供给 while 循环,例如

      while read -r pkgdir; do
          ## do what you need with "$pkgdir"
      done < <(find /path -type d -name "pkg_*")
      

      注意:&lt; &lt;之间必须有空格)

      find 命令将定位所有目录-type d/path 下,其中名称与全局"pkg_*" 匹配。这些将由while 循环读取到变量pkgdir 中。然后,您可以以任何需要的方式处理"$pkgdir" 中的目录。

      您还可以使用-exec 选项来查找执行所需的任何单个命令或在每个目录上调用另一个脚本。您还可以将结果通过管道传输到 xargs 并完成相同的操作(建议在 find 中使用 -print0 以输出以 nul 结尾的目录名称,并为 xargs 使用 -0 选项以表示相同)

      如果您有任何其他问题,请告诉我。

      【讨论】:

      • 好吧,首先,bash: read: '/home/cabox/': not a valid identifier 成为一个问题(这是针对 codeanywhere 的 Ubuntu bash),其次我只需要知道 pkg_* 仅存在于指定的目录中。 find 函数正在查看所有子目录,导致与其他不相关但共享公共 pkg_* 的文件夹出现问题 另外,为什么 find 函数在 done 之后?我需要在目录存在的情况下执行一个动作,所以我不知道如何将它应用到bash(我是初学者,如果你看到我的github你就会知道)。
      • 您可以限制find 将使用-maxdepth 1 选项搜索的深度(它必须是/path 之后的第一个选项)。例如。 (1 当前/path2 用于/path/firstlevelsubs,等等...)
      猜你喜欢
      • 2020-12-16
      • 1970-01-01
      • 1970-01-01
      • 2023-02-13
      • 1970-01-01
      • 2013-03-06
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      相关资源
      最近更新 更多