find:列出除名称中带有数字的目录及其子目录之外的所有目录

find:列出除名称中带有数字的目录及其子目录之外的所有目录

我正在运行以下命令来查找所有没有数字的目录(不包括原始路径):

find /path/2/directory -type d -name '[!0-9]*'

问题是它找到的目录是具有数字的目录的子目录。

例子:

/path/2/directory/20160303/backup

甚至

/path/2/directory/backup20160303a/backup

有什么办法可以防止 find 返回此类目录吗?

我无法通过限制深度来解决这个问题,深度可以变化。

例子:

/path/2/directory/subdirectory/20160303/backup

答案1

用于-prune忽略这些目录:

find /path/to/directory -name '*[0-9]*' -prune -o -type d -print

不过,如果您正在进行gnu设置,则可能希望C在运行上述命令时使用区域设置,请参阅下面 Stéphane 的评论。

答案2

如果您不想 find 下降到超出某个匹配项,您应该使用-pruneand 而不是例如或过滤with-path的输出findgrep -v

为了进行测试,请创建一个包含一些额外文件和子目录的环境,以便您可以检查是否find不显示不需要的材料:

mkdir -p tmp/2/abc/def
touch tmp/2/abc/def/file1
mkdir -p tmp/2/abc/9876/xyz
touch tmp/2/abc/9876/xyz/file2
tree tmp/

给出:

tmp
└── 2
    └── abc
        ├── 9876
        │   └── xyz
        │       └── file2
        └── def
            └── file1

如果您find tmp/2/abc \! -path "*[0-9]*"按照@terdon的建议进行操作,则输出将为空,因为-path不仅考虑从下面开始的目录abc,还考虑整个路径,其中包括2.所以这不是你想要的。

如果您find tmp/2/abc -type d | grep -vE '/[0-9-]+(/|$)'按照@cas的建议这样做,您会发现它也不会打印任何内容,因为它不仅匹配您正在搜索的文件,还匹配名为 的目录2。除此之外,这需要 find 首先遍历整个树9876,如果那里有几十万个项目,则遍历(和过滤)将花费大量时间。

如果你这样做:

find tmp/2/abc -type d -name '[!0-9]*' -print 

你会发现输出包含路径tmp/2/abc/9876/xyz。要摆脱它,请切断你不想要的东西-prune

find tmp/2/abc -type d -name '[!0-9]*' -print -o -name '[0-9]*' -prune

这使:

tmp/2/abc
tmp/2/abc/def

您可以通过交换修剪和打印来稍微提高效率,这就是@don_cristti 在增强这个答案时所做的。

答案3

我想您正在寻找-path

   -path pattern
          File  name matches shell pattern pattern.  The metacharacters do
          not treat `/' or `.' specially; so, for example,
                    find . -path "./sr*sc"
          will print an entry for a directory called `./src/misc' (if  one
          exists).  

它在每个文件/目录的整个路径中搜索给定的模式。因此,如果您有这样的目录结构:

$ tree
.
├── 111
│   └── foo
│       └── bar
├── bar
│   └── foo
│       └── baz
└── foo
    └── 111
        └── bar

9 directories, 0 files

你可以find这样使用:

$ find /path/to/directory/ \! -path "*[0-9]*" 
.
./foo
./bar
./bar/foo
./bar/foo/baz

或者,使用 GNU find

find /path/to/directory/ -not -path "*[0-9]*" 

由于这必须深入到每个目录来检查其名称,因此在大型目录树上它会比在大型目录树上慢得多@Anthon的解决方案与李子。不过,如果您没有数千个目录,那应该没问题。

答案4

grep使用(或awksed或等)从的输出perl中删除此类目录很容易:find

find /path/to/directory -type d | grep -vE '/[0-9-]+(/|$)'

注意:我已将其包含-在字符类中,因为带日期的目录有时是 YYYY-MM-DD 而不仅仅是 YYYYMMDD

相关内容