我有一个大型项目,我正在尝试查找不包含文件的目录*_out.csv
。我看过其他类似的答案,我想我已经差不多了。
我遇到的问题是,我只想查看继续进行分析的目录analysis/
,但我也不想查看也进行分析的一些特定目录。
我设置了一个小示例问题:
$ tree
.
├── case1
│ ├── analysis
│ │ ├── test1
│ │ │ ├── gold
│ │ │ └── test1_out.csv
│ │ └── test2
│ └── doc
└── case2
├── analysis
│ ├── test3
│ │ └── gold
│ └── test4
│ └── test4_out.csv
└── doc
12 directories, 2 files
我不想查看标题为*/doc/*
或 的目录*/gold/*
。我当前的命令是:
find . -type d -not -name "doc" -not -name "gold" '!' -exec test -e "{}/*_out.csv" ';' -print
结果是:
.
./case1
./case1/analysis
./case1/analysis/test1
./case1/analysis/test2
./case2
./case2/analysis
./case2/analysis/test3
./case2/analysis/test4
我理想的输出是这样的
./case1/analysis/test2
./case2/analysis/test3
正如您所看到的,我当前的find
命令排除了doc
和gold
目录,但它不排除有*_out.csv
文件的目录,也不排除不继续的目录analysis/
。
答案1
因此,您想要查看表单的目录*/analysis
,不包括某些子目录。
不要搜索下面的所有内容.
,而只搜索下面的内容*/analysis
。
要排除子目录,请使用-prune
.这是一个告诉 find 不要递归遍历该子目录的操作。
最后,要测试是否存在与模式匹配的文件,您需要调用 shell。您test
直接从调用find
,但test
不进行模式匹配,因此它只是测试名称包含文字*
字符的文件是否存在。调用sh
,将目录名称作为参数传递给它:-exec sh -c '…' {} \;
。在 sh 代码中,展开通配符以生成匹配文件列表,并检查是否至少有一个现有文件。
find ./*/analysis -name "doc" -prune -o -name "gold" -prune -o \
-type d \! -exec sh -c 'set -- "$0"/*_out.csv; test -e "$1"' {} ';' -print
(我假设不存在名称以 结尾的悬空符号链接_out.csv
。)
答案2
你的任务是重复的这个问题。同样的策略也将发挥作用:
找到所有 *_out.csv 文件,去掉基本名称并对列表进行 uniq。
找到所有你想要的目录希望将有 *_out.csv 文件,并从步骤 2 的列表中删除列表 1 中的条目。
该脚本使用输出描述符来执行此操作:
echo "csv files exist in:"
find . -type f -name \*_out.csv | sed -e 's/\/[^\/]*$//' |
sort -u | tee csv-dirs.txt
echo
echo "dirs we hope would have csv's:"
find . -type d | egrep '/analysis/' | egrep -v '/(doc|gold)(/.*|)$' |
tee all-dirs.txt
echo
echo "all dirs less the ones that do have csv's:"
egrep -vxFf csv-dirs.txt all-dirs.txt
稍微浓缩一下,可能就是:
$ find . -type f -name \*_out.csv |
sed -e 's/\/[^\/]*$//' | sort -u > csv-dirs.txt
$ find . -type d | egrep '/analysis/' |
egrep -v '/(doc|gold)(/.*|)$' | egrep -vxFf csv-dirs.txt
./case1/analysis/test2
./case2/analysis/test3