搜索包含一个文件但缺少另一个文件的目录

搜索包含一个文件但缺少另一个文件的目录

我目前知道如何搜索目录并列出不包含特定文件的目录,如下所示:

find parent_directory -mindepth 1 -maxdepth 1 -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^file_name$"' \; -print

但现在我想使用结果目录来检查它们是否包含另一个文件,但我无法在扩展的单行表达式中做到这一点。这有可能吗?

答案1

您还可以通过以下方式确定所需的目录:

find . -maxdepth 2 -path '*/*/wanted.txt' -type f \
  -execdir test ! -f unwanted.txt \; -execdir pwd \;

其工作原理如下:

  • 我们寻找深度为 2 的条目。
  • 由于存在 2 个斜杠,该-path选项将进一步将它们限制为深度为 2,因为最大深度阻止进一步前进,并且 2 个显式斜杠阻止深度低于 2。
  • 在深度级别 2 找到的 Wanted.txt 条目最好是一个常规文件,并通过以下方式确保-type f
  • -execdir选项会将操作提升到 Wanted.txt 所在的目录,因此该test命令将在那里查找不需要的文件。
  • -execdir接下来,打印未找到不需要的文件的目录(由于 而提升)是一个简单的问题。
  • 无意详述这一点,一个目录只能包含一次特定文件,因此-execdir操作在 /directory 上运行一次,并且仅在那些至少确定包含 Wanted.txt 常规文件的目录上运行。

答案2

You are making this far more complicated than needed. You don't seem to want to recurse into subdirectories, so all you need to find those directories that don't have a specific file is:

for dir in */; do [ ! -e "$dir"/"$filename" ] || printf '%s\n' "$dir"; done

并且,要查看其中哪些确实有另一个文件:

for dir in */; do 
    [ ! -e "$dir"/"$filename1" ] && 
    [ -e "$dir"/"$filename2" ] && 
    printf '%s\n' "$dir"; 
done

或者,用稍微清晰的语法:

for dir in */; do 
    if [ ! -e "$dir"/"$filename1" ]; then 
        if [ -e "$dir"/"$filename2" ]; then 
            printf '%s\n' "$dir"; 
        fi 
    fi
 done

这一切都是使用 shell 的内置工具完成的。具体来说:

  • [:这个以及随附的内容]是内置函数的同义词test(请参阅help [help test如果使用 sh 风格的 shell)。它们是在 shell 中编写测试操作的方法。
  • -e:这测试文件/目录等是否存在。看help test。简单的格式是:如果存在[ -e file ]则返回 true 。file
  • [ ! -e filename ]!简单地反转测试。如果确实如此,那[ ! -e file ]就是真的file不是存在。

总而言之,这意味着上面的命令执行以下操作:

## Iterate over every directory (dirs only because of the '/' in '*/')
## saving each of them in the variable $dir.
for dir in */; do 
    ## If this $dir does not contain $filename1
    if [ ! -e "$dir"/"$filename1" ]; then 
        ## If this $dir does contain $filename2
        if [ -e "$dir"/"$filename2" ]; then 
            ## Print the directory name
            printf '%s\n' "$dir"; 
        fi 
    fi
done

当然,要运行它,您需要首先进行$filename1相应的设置$filename2。例如:

filename1="unwantedFile"
filename2="wantedFile"

答案3

使用zsh, 列出当前目录中包含文件musthave而不是mustnothave文件的目录:

contain() [[ -e $REPLY/$1 || -L $REPLY/$1 ]]

printf '%s\n' *(D/e(contain musthave)^e(contain mustnothave))

请注意,执行以下操作:

find ... -exec sh -c 'ls {}' \;

不仅不可移植,而且还是一个命令注入漏洞。例如,如果有一个名为$(reboot)或 的目录;reboot,则会运行ls $(reboot)ls ;reboot命令行,从而导致重新启动。{}永远不应该嵌入到(或任何其他语言的)代码参数中,sh否则可能会被误解。使用:

find ... -exec sh -c 'ls "$1"' sh {} \;

反而。

相关内容