简短版本:
我正在尝试编写一个bash命令,该命令将根据某些文件的存在和/或不存在生成子目录列表。如果目录名称包含名为“Ready”的文件并且不包含名为“Complete”或“Failed”的文件,则该目录名称将包含在列表中。基于我在这里看到的例子,我一直在使用'find'命令,但是我对它没有足够的把握或一般的bash来使它工作。
find . -maxdepth 1 -name Ready | find -mindepth 1 -maxdepth 1 -type d '!' -exec test -e "{}/Complete" ';' -print | find -mindepth 1 -maxdepth 1 -type d '!' -exec test -e "{}/Failed" ';' -print
长版:
在我们的系统中,另一个组会删除由我们的某个应用程序处理的文件目录(“bundle”)。这些目录可以包含一个或多个零长度状态文件,这些文件指定捆绑包已准备好进行处理(“就绪”),或者应该被忽略,因为它已成功处理(“已完成”)或之前出现错误(“失败” “)。
系统的大部分都是购买的软件,我们开始开发一些自行开发的监控,管理和指标收集工具。我正在尝试编写一个脚本,它将在任何给定时间查看这些目录,并根据状态文件的存在与否来确定哪些已准备好进行处理,哪些将被忽略。
答案 0 :(得分:1)
假设您正在使用bash
4或更高版本,我将跳过find
并迭代递归的glob **/*/
。
shopt -s globstar nullglob
for d in **/*/; do
[[ -e $d/Ready ]] || continue # Skip directories without a Ready file
[[ -e $d/Completed ]] && continue # Skip directories with a Completed file
[[ -e $d/Failed ]] && continue # Skip directories with a Failed file
print '%s\n' "$d" # If you made it this far, print the directory name
done
这可以浓缩为
shopt -s globstar nullglob
for d in **/*/; do
[[ -e $d/Ready && ! (-e $d/Completed || -e $d/Failed) ]] && printf '%s\n' "$d"
done
您也可以使用glob来标识包含Ready
的目录:
for f in **/*/Ready; do
d=${f%Ready}
[[ -e $d/Completed || -e $d/Failed ]] || printf '%s\n' "$d"
done
答案 1 :(得分:0)
您可以使用find
选项not
匹配某些名称:
find . -maxdepth 2 -path "*Ready*" ! -name "Failed" -a ! \
-name "Complete" -exec bash -c 'echo "$0"' {} \;
在嵌套目录-path
中,只能找到“Ready”目录中不包含(!
)“Failed”或“Complete”的文件。例如:
$ ls
Complete Failed Ready outdir sub1 sub2 sub3
$ cd Ready ; ls
Complete Failed Ready somefile
从父目录使用上面的find
命令将产生:
./Ready
./Ready/Ready
./Ready/somefile
如果您将-path
切换为-name
,您将获得:
./Ready
./Ready/Ready
find
是一款功能强大的实用工具,可以根据搜索范围内的任何需求进行调整。
答案 2 :(得分:0)
这是一件简单的事。
从find
命令开始,找到用作触发器的文件。把它管成一个" grep"这将摆脱文件名,排序,消除重复,如:
find . -type f -name Ready -o -name Completed -o -name Failed | grep -o "^.*/" | sort | uniq
在-maxdepth 2 -mindepth
之前添加-type f
2,将深度限制为1级。