如何测试Linux目录是否只包含一个子目录而没有其他文件?

时间:2015-09-06 23:35:25

标签: linux sh

/bin/sh脚本中,我想检查目录是否只包含一个子目录而不包含其他文件(当然除了“。”和“..”)。我可以解析ls的输出,但我也明白这通常是一个坏主意。建议?

问题的原因:当我zip一个文件夹,比如一台Windows机器,我在Linux下解压缩时,有时我会得到一个目录,其内容是原始文件夹的内容;有时我得到一个目录只包含一个子目录,其内容是原始文件夹的内容。 (我假设我在Windows下使用zip的方式有所不同,或者我使用的各种Windows机器配置略有不同,或者......谁知道?)不管怎样,我想,在Linux方面,以大致相同的方式处理这两种结果,因此这个问题。

对于那些想“如果你的Windows端文件夹真的 只包含一个子目录怎么办?”,那么在这种情况下就好了,虽然我认为这是一个角落的情况。问题规范。

5 个答案:

答案 0 :(得分:4)

public class HackHornets_Roster { enum MembershipStat {CoPresident, Secretary, Treasurer, RegMember,Sponser} public static void main (String[] args) { final int CoPresidents = 2; // declare members MembershipStat ChaseW; MembershipStat Saif; MembershipStat MrLee; MembershipStat Rahil; MembershipStat Donovon; MembershipStat Elliot; MembershipStat Armaan; MembershipStat JacksonM; MembershipStat Cyrus; MembershipStat Avery; MembershipStat PeterM; MembershipStat Mahdi; MembershipStat GeorgeW; // assign Member Roles ChaseW = MembershipStat.CoPresident; Saif = MembershipStat.CoPresident; MrLee = MembershipStat.Sponser; Rahil = MembershipStat.Secretary; Donovon = MembershipStat.RegMember; Armaan = MembershipStat.RegMember; Elliot = MembershipStat.RegMember; // Marching Band JacksonM = MembershipStat.Treasurer; Cyrus = MembershipStat.RegMember; // sports Avery = MembershipStat.RegMember; // sports PeterM = MembershipStat.RegMember; // sports Mahdi = MembershipStat.RegMember; GeorgeW = MembershipStat.RegMember; System.out.println("Chase Williams: " + ChaseW); System.out.println("Saif Ali: " + Saif); } } 将是一个很好的工具。它有一些巧妙的论点:

  • find因此不会递归搜索
  • -maxdepth 1仅搜索目录
  • -type d用奇怪的文件名解决问题(打印-printf 1而不是文件名)

然后是完整的命令:

1

这将为每个目录和目录本身打印一个字符,这样您就可以查找打印两个字符的目录(find有一个很好的功能,在搜索时忽略find DIRECTORY -maxdepth 1 -type d -printf 1 .

然后,您要检查是否没有其他(非目录)文件:

..

全面检查将是:

find DIRECTORY -maxdepth 1 ! -type d -printf 1

或者,您可以使用if [ "$(find DIRECTORY -maxdepth 1 -type d -printf 1 | wc -m)" -eq 2 \ -a "$(find DIRECTORY -maxdepth 1 ! -type d -printf 1 | wc -m)" -eq 0 ]; then # It has only one subdirectory and no other content fi 的{​​{1}}创建一个命令,打印文件类型(-printf用于目录):

%y

答案 1 :(得分:1)

/bin/sh中您遇到的最大问题是隐身文件,因为*无法捕获[默认]。

我认为这会做你想做的事情:

#!/bin/bash
count_()
{
    echo $(( $# - 2 )) # -2 to remove . and ..
}
count()
{
    count_ * .*
}
ITEM_COUNT=$(count)

当然,如果您愿意,您可以根据路径进行调整。

示例输出:

bash-3.2$ count
3
bash-3.2$ ll
total 0
drwxr-xr-x   5 christopher  wheel  170 Mar 18  2014 .
drwxrwxrwx   6 root         wheel  204 Jul  5 12:28 ..
drwxr-xr-x  14 christopher  wheel  476 Mar 18  2014 .git
drwxr-xr-x   5 christopher  wheel  170 Mar 18  2014 bin
drwxr-xr-x   4 christopher  wheel  136 Mar 18  2014 pylib

另一个例子:

sh-3.2$ count_()
> {
>     echo $(( $# - 2 )) # -2 to remove . and ..
> }
sh-3.2$ count()
> {
>     count_ * .*
> }
sh-3.2$ ITEM_COUNT=$(count)
sh-3.2$ echo ${ITEM_COUNT}
3

<强>旁注:

你说不同的拉链实现处理方式不同,但在Linux上,许多工具以不同的方式处理zip /path/to/folderzip /path/to/folder/ (这是荒谬的烦人的)。如果您在受控环境中工作,则可能需要规范化压缩事件的方式。但是,如果这是一个面向用户的事情,那就太糟糕了。

如果你没有使用bash作为调用shell:

countFiles.sh

#!/bin/bash
count_()
{
    echo $(( $# - 2 )) # -2 to remove . and ..
}
count_ * .*

scriptThatWantsTheCountOfFiles

#!/bin/tcsh
set count = `./countFiles.sh`

答案 2 :(得分:0)

为避免必须自行解析输出,您可以使用find

if [[ `find . -type d | wc -l` -eq 2 && \
      `find . -type f | wc -l` -eq 0 ]]; then

  echo yes

else

  echo no

fi

如果您想避免递归到目录,可以指定-maxdepth 1

有关其他一些选项,请参阅man find

答案 3 :(得分:0)

指向目录inode的链接数量可以有所帮助,但不能完全解决问题。一个目录有2 + n个指向它的链接,n内部创建的子目录数。因此,如果您尝试查找仅包含3个链接的所有目录,那么您将获得仅包含一个子目录的目录。但获取无文件目录的唯一解决方案是搜索它。

也许你可以在混合的两阶段解决方案中思考,首先你会发现所有带有3链接的目录指向它们(非常有效)。然后你只读那些,发现里面没有普通文件。

答案 4 :(得分:0)

这是一个便携式shell函数,在Dash中测试:

check() {
    d=
    for i in "$1"/* "$1"/.* 
    do
        test ddd != "$d" && test -d "$i" || return 1
        d=d$d
    done
    test ddd = "$d"
}

我们使用变量d来计算我们看到的目录数量。我们期待三个(...和目标目录。如果我们已经看过三个,那就提前退出;同样,如果我们看到一个非目录。

如果我们到循环结束,我们检查我们已经看到三个目录; test的返回值成为函数的返回值。