如何查找并打印目录中丢失的文件?

如何查找并打印目录中丢失的文件?

我想查找并列出父目录中包含以 .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

这是一个两步解决方案。总体来说,流程是:

  1. 查找*.grid路径中的所有文件,删除基本文件名和uniq列表。这将为您提供包含一个或多个文件的所有目录的列表*.grid

$ find /work/user/folder1/*/*/ -type f -name *.grid | sed -e 's-[^/]*$--' | sort | uniq > grid-dirs.txt

  1. 查找路径中的所有目录,并用于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 上运行良好。

相关内容