在bash中检查是否存在符合特定条件的目录

3

我正在尝试让bash检查一个目录是否存在,但只有当它符合特定的条件时才检查。

例如,我想检查以 pkg_ 开头并跟随任何其他字符的目录是否存在。

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

目前代码大致如下:

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

但是每次运行它,都会返回false,无论是否存在以“pkg_”开头的任何目录。
同时,使用“cd ~/pkg_*”可以正常工作,我能够进入该目录。
4个回答

2
shopt -s nullglob
for path in ~/pkg_*/
do
    [do what you want if at least one such directory exists]
    break
done

解释:
  • 设置 nullglob 可以确保如果不存在这样的目录,则 ~/pkg_*/ 解析为空字符串,这意味着我们不会进入循环。
  • 末尾的斜杠确保我们只匹配目录,而不是普通文件。
  • 展开波浪号和星号,需要将这些字符取消引用。如果加上引号,则匹配文件名中的字面波浪号和星号字符,这种情况非常罕见。
  • 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!

0

这取决于您需要查找目录的位置。如果您只需要检查单个目录中是否有名为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_*")

(注意: < < 之间需要有空格)

find 命令将定位所有目录 -type d,这些目录在 /path 下匹配 glob "pkg_*"。这些目录将被读入变量 pkgdir 中的 while 循环中。然后,您可以按任何所需的方式处理目录中的 "$pkgdir"

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

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


首先,对于Codeanywhere的Ubuntu bash,bash: read: '/home/cabox/': not a valid identifier会成为一个问题。其次,我只需要知道pkg_*仅存在于指定的目录中。find函数正在查找所有子目录,这会导致与其他无关但共享公共pkg_*的文件夹出现问题。另外,为什么find函数在done之后?我需要在存在目录的条件下执行操作,所以我不知道如何将其应用到bash中(我是初学者,如果您看到我的github,您就会知道)。 - Find Me In The Woods
你可以使用 -maxdepth 1 选项来限制 find 命令的搜索深度(它必须是 /path 后面的第一个选项)。例如:(1 表示当前 /path2 表示 /path/firstlevelsubs 等等...) - David C. Rankin

-1

虽然不是优雅的一行代码,但你可以尝试这个:

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

然而,这样做的副作用是,如果您有多个匹配的文件夹,则会执行多次操作。

顺便说一句,在第一行中,我使用环境变量$HOME代替波浪号,因为波浪号无效。

我已经测试过了,它似乎也在经典的Bourne shell中有效。

Bash专家们可能有更好的答案。


@l0b0 我在想我错过了什么。除了我明确提到的多个匹配项之外,这对我很有效。这就是你指的吗? - Greg Elliott
明白了。文件或目录名称中的空格导致失败。但是在“$f”周围简单添加引号可以纠正这个问题。是的,那么它仍然会匹配多个文件夹。这取决于确切的意图是好是坏。OP没有说明是否允许多个匹配。 - Greg Elliott

-1

你可以像这样做。

#!/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 你测试了吗? - ntshetty
@l0b0 让我看看你试图否定的例子。 - ntshetty
是的,我测试过了。当“find”找到两个目录时,它运行了两次。 - l0b0
他没有提到路径中只有一个目录。我的解决方案是通用的吗? - ntshetty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接