繁体   English   中英

如何查找/列出不存在特定子目录的目录

[英]How to find/list the directories where a particular sub-directory is not present

我正在编写一个shell脚本,它正在检查bin目录是否存在于/ home目录下的所有users目录下。 bin目录可以直接存在于用户目录下或用户目录的子目录下。
我的意思是说我有一个用户作为/ home下的amit。 因此bin目录可以直接作为/ amit / bin存在,也可以作为/ amit / jash / bin存在

现在我的要求是我应该有一个用户目录列表,其中bin目录不存在于用户目录下或用户目录的子目录下。 我尝试了命令: find / home -type d! -exec test -e'{} / bin'\\; -print但它不起作用。 但是,当我用某个文件替换bin目录时,该命令工作正常。 看起来这个命令特别适用于文件。 目录有没有类似的命令? 任何有关这方面的帮助将不胜感激。

你走在正确的轨道上。 问题是你的测试“在这个目标中不存在以下目录”不能在find的条件下表达,只能返回顶级目录。 所以你需要以某种方式进行嵌套。

一种策略是在bash中使用for循环:

$ mkdir foo bar baz one two
$ mkdir bar/bin baz/bin
$ for d in /home/*/; do find "$d" -type d -name bin | grep -q . || echo "$d"; done
foo/
one/
two/

这使用路径名扩展(globbing)来生成要测试的目录列表,然后检查是否存在“bin”。 如果检查失败(即找不到输出),则打印目录。 注意/home/*/上的尾部斜杠,它确保您只在目录中搜索,而不是在/home/偶然存在的文件。


另一种可能是使用嵌套的find ,如果你不想依赖bash:

$ find /home/ -type d -depth 1 -not -exec sh -c "find {}/ -type d -name bin -print | grep -q . " \; -print
/home/foo
/home/one
/home/two

这大致重复了上面的bash for循环的效果,但是通过在find -exec嵌套find 它使用grep -q . find的输出转换为退出状态,可以将其用作外部 find的条件。

请注意,由于您正在寻找bin目录 ,我们希望使用test -d而不是test -e (它也会检查bin 文件 ,这对您来说可能无关紧要。)


另一种选择是使用bash进程重定向。 在多行上以便于阅读:

cd /home/
comm -3 \
  <(printf '%s\n' */ | sed 's|/.*||' | sort) \
  <(find */ -type d -name bin | cut -d/ -f1 | uniq)

遗憾的是,这需要您在运行之前更改到/home目录,因为它会剥离子目录。 如果你有这种倾向,你当然可以将它折叠成一个很长的单线。

comm解决方案还存在在名称中包含特殊字符的目录失败的风险,如换行符。


最后一个选择是bash-only,但不仅仅是单行。 它涉及从完整列表中减去包含“bin”的目录。 它使用关联数组和globstar ,因此它依赖于bash版本4。

#!/usr/bin/env bash

shopt -s globstar

# Go to our root
cd /home

# Declare an associative array
declare -A dirs=()

# Populate the array with our "full" list of home directories
for d in */; do dirs[${d%/}]=""; done

# Remove directories that contain a "bin" somewhere inside 'em
for d in **/bin; do unset dirs[${d%%/*}]; done

# Print the result in reproducible form
declare -p dirs

# Or print the result just as a list of words.
printf '%s\n' "${!dirs[@]}"

请注意,我们将目录存储在数组索引中 ,其中(1)使我们可以轻松查找和删除项目,以及(2)确保唯一条目,即使一个用户在其主目录下有多个“bin”目录。

cd /home
find . -maxdepth 1 -type d ! -name . | sort > a
find . -type d -name bin | cut -d/ -f1,2 | sort > b
comm -23 a b

在这里,我正在制作两个排序列表。 第一个包含所有主目录,第二个包含任何bin子目录的顶级父目录。 最后,我输出第二个中不存在的第一个列表中的任何项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM