我想查找并列出父目录中包含以 .grid 结尾的文件的所有目录/work/user/folder1/*/*
find /work/user/folder1/*/*/ '!' -mindepth 1 -maxdepth 1 -name *.grid
我想做的下一步是找到所有缺少以 .grid 结尾的文件的目录基本上我希望命令打印出丢失的文件夹。
我怎样才能做到这一点?
答案1
用来find
打电话find
!
find . -type d \( -exec sh -c 'cd "$0"; find . \( -name . -o -prune \) -name "*.grid" | grep -q .' {} \; -o -print \)
这是 POSIX 兼容的,感谢这个答案:
此外,无论文件名或目录名中是否有空格、特殊字符甚至换行符,这都将起作用。 :)
(注:如果你做如果您的目录名称中有特殊字符或换行符,您应该将最终的-print
主要更改为您想要对目录执行的任何操作,因为如果您只使用 ,您将无法安全地解析生成的打印列表-print
。)
这是一个添加换行符的版本,可能是为了提高可读性而误导的:
find . -type d \
\( \
-exec sh -c '
cd "$0";
find . \( -name . -o -prune \) -name "*.grid" |
grep -q .
' {} \; \
-o -print \
\)
答案2
步骤 1.) 创建所有适用目录的列表,按字母数字顺序对其进行排序,并确保没有重复项。将列表保存在临时文件中:
find /work/user/folder1/ [...] -type d | sort | uniq > all_directories.txt
步骤 2.) 创建所有文件的列表*.grid
。
find /work/user/folder1/ [...] -name *.grid > grid_files.txt
步骤 3.) 浏览文件列表*.grid
,获取每个文件的目录名称,并再次确保没有重复项:
while read FILENAME
do
echo $(dirname "$FILENAME")
done < grid_files.txt | sort | uniq > dirs_with_gridfiles.txt
步骤 4.) 将这两个列表一起运行并再次对结果进行排序。现在,*.grid
应该列出包含文件的目录确切地各两次,并且目录没有*.grid
文件确切地各一次。所以你可以告诉uniq
只报告非重复的行:
cat all_directories.txt dirs_with_gridfiles.txt | sort | uniq -u > dirs_with_no_gridfile.txt
你就得到它了。
答案3
这是一个两步解决方案。总体来说,流程是:
- 查找
*.grid
路径中的所有文件,删除基本文件名和uniq
列表。这将为您提供包含一个或多个文件的所有目录的列表*.grid
。
$ find /work/user/folder1/*/*/ -type f -name *.grid | sed -e 's-[^/]*$--' | sort | uniq > grid-dirs.txt
- 查找路径中的所有目录,并用于
grep
过滤掉步骤 1 中找到的目录。这将为您提供不包含任何*.grid
文件的所有目录的列表。
$ find /work/user/folder1/*/*/ -type d | grep -Fvxf grid-dirs.txt
例如,假设:
$ find /work
/work
/work/user
/work/user/folder1
/work/user/folder1/AA
/work/user/folder1/AA/AA
/work/user/folder1/AA/DD
/work/user/folder1/AA/CC
/work/user/folder1/AA/BB
/work/user/folder1/AA/BB/foo.grid
步骤1之后,grid-dirs.txt
是:
/work/user/folder1/AA/BB/
步骤2的输出为:
$ find /work/user/folder1/*/*/ -type d | grep -Fvxf grid-dirs.txt
/work/user/folder1/AA/AA/
/work/user/folder1/AA/CC/
/work/user/folder1/AA/DD/
答案4
如果您有 Bash v4(或更高版本),我认为您也可以通过一个循环查找所有*.grid
文件,再加上一个内部循环遍历所有目录来列出哪些目录有文件,哪些目录没有。对于 Bash v4,我们使用通常被禁用的选项之一。
(
# 'globstar' enables '**' expansions, which instructs
# the shell to search all and below recursively
shopt -s globstar
# Note that '**' is implicitly recursive, no need to specify
# depth. If you do want to specify precise depth, then use a
# '*/' for each wanted depth, like '*/*/*/' for 3 depths
for f in /work/user/folder1/**/*.grid; do
f="${f##*/}" # strip directory from found name
printf '\nNow looking for: %s\n' "$f"
# A simple '**/' returns directories only
for d in /work/user/folder1/**/; do
# simple existence test
[ -e "${d}${f}" ] && \
printf ' present in %s\n' "$d" || \
printf 'not present in %s\n' "$d"
done
done
)
不幸的是,**
语法不是 POSIX。
但是,如果您知道需要搜索的精确深度,只需去掉该shopt
命令并将每个命令转换**/
为以重复表示的精确深度*/
,它也应该在 POSIX shell 上运行良好。