【问题标题】:How to list all sub-directories containing a file如何列出包含文件的所有子目录
【发布时间】:2011-08-05 12:03:55
【问题描述】:

我必须完成以下任务:

对于给定的文件名列表和给定的目录,为每个文件名打印它出现的所有子目录。子目录将根据文件的创建日期以降序打印。

我不知道该怎么做

【问题讨论】:

  • 张贴您迄今为止尝试过的内容,以及您遇到困难的领域。
  • 同意,向我们展示您所拥有的并寻求对困难部分的澄清。要求别人为你做作业不会走得太远(你将如何学习?)
  • 我认为这个问题也很模糊。您是否获得了一组示例文件/目录来处理?
  • 问题不成立。除非您使用的是非标准文件系统,否则该文件的创建日期不可用。

标签: linux file shell directory


【解决方案1】:
for file in $(< filelist) 
do 
    find -name "$file" -printf "%C@ %h\n" | sort -rn | sed 's/^[0-9.]* //'
done 
  • $(
  • printf %C@ 以秒为单位打印自 1.1.1970 以来的时间
  • %h 打印没有文件名的前导目录
  • sort -n 排序数字,-r 倒序
  • sed 删除排序后的时间

问题:

  • 从问题来看,没有迹象表明要打印文件名本身,这对于现实世界的场景来说是不寻常的。这很容易解决。
  • 带有换行符的路径名以及其他花哨的字符(如垂直制表符、换页符等)处理不当。

【讨论】:

    【解决方案2】:

    因为想出个人最喜欢的解决方案很有趣,所以我会加入:

    解决方案(剧透)

    @用户未知:

    我知道你在拖钓,但为了普通读者的兴趣: 我承认那里的内联扩展确实不安全。我真的在展示我打算如何组合使用命令(ls、find、uniq)等。它可以变得安全:

    find -type f -printf '%f\0' | sort -uz |
        xargs -0i -n1 find -name {} -printf "%f:%p\n"
    

    现在格式化稍微不方便了(再说一次,如何你会用路径名中的特殊字符来格式化它吗?)。这个问题对这个主题几乎没有说明,所以......


    最后一点:

    the first read is already broken with (...) blanks in filenames

    • 不真实 while read 只被换行符打破,试试看:read line &lt;&lt;&lt; "a b c" &amp;&amp; echo "'$line'"

    原始教学指针

    使用

    dirname
         a/b/c/file -> a/b/c
    basename
         a/b/c/file -> file
    ls -t / ls -tr
         sort files by timestamp; note that 'creation date' is likely a fob because hardly any filesystem stores these reliably (it is usually the last change date for the inode)
    
    find -type f
    find -type d
         find files or directories
    sort | uniq
    sort -u
         sort lines and remove adjacent (subsequent) duplicates
    

    如果有帮助,请告诉我。除了指向 UNIX 命令的指针之外,我还可以给你一个小小的改进

    【讨论】:

    • 您不需要 dirname、basename、ls -t、ls -tr、uniq 或 sort -u。唯一性不是必需的。
    • 告诉我你的解决方案,然后我们会谈谈:)
    • 我做了 :) 以及实现我自己的概念解决方案,所以您可以自己确认 Tim Toady
    • 对不起,你的程序会为我生成这样的输出:: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 如果我用我的文件列表提供它。原始程序根据找到的内容生成自己的文件列表,与要解决的任务不同,会产生许多错误消息ls: cannot access noch.mp: No such file or directory dirname: missing operand Try dirname --help' 以获取更多信息。`它仅适用于经过清理的目录和文件名。原因是:第一个 read fname 已经被 (...) 打破了
    • (...) 文件名中的空格。下一部分:$(ls -t $(find -name "$fname") 再次不会阻止在空格处分词,以及 xargs。在您的测试实验室中放一些带空格的文件名和带空格的目录名,然后重试。
    【解决方案3】:

    您可以结合使用for(循环遍历您的文件)和find 来搜索您的文件。

    cat > filenames <<EOF
    file-a
    file-b
    file-c
    EOF
    
    export DIR=dir-d
    
    for filename in `cat filenames`; do find $DIR -name $filename ; done
    

    查看“查找”手册页,了解您还可以做什么;您可以轻松运行其他命令(使用-exec)。

    【讨论】:

    • 您不需要导出DIR,只需分配:DIR=dir-d
    • 有些东西应该留给学生。 :-)
    【解决方案4】:

    它只能在 Linux 下工作,但那是在 OP 中:

    #!/bin/sh
    
    for file in fileNameA fileNameB; do
      echo "File ${file} is in the following directories:"
      find sourceDir -type f -name ${file} -printf "%T@\t%h\n"|sort -rn|cut -f2
    done
    

    提示:如果您省略 cut -f2 部分,您还可以看到文件的创建(最后修改)时间。

    【讨论】:

    • 剪切 -d2 还是 -f2?如果我省略它,我会看到,对于非常旧的文件,如果没有 -n 开关,排序会失败。
    【解决方案5】:

    文件的创建日期通常不可用。在标准文件系统上,您可以访问上次修改时间、上次访问时间和上次更改元数据的时间。除了那个问题,这里有一个很好的脚本来做其他部分:

    #!/bin/sh F=$(mktemp) 陷阱“rm -f $F”0 查找 ${1? 用法:$(basename $0) path [file...]} > $F 转移 同时测试 $# -gt 0;做 grep $1 $F 转移 完毕

    这个脚本的一个很好的特点是它只运行一次 find 。要进行排序,一种好的技术是将要排序的统计信息打印到临时文件中,然后简单地通过管道输出 while 循环的输出以进行排序。如评论中所述, grep 并不是特别可靠,因为它可能匹配不完全匹配的路径。

    【讨论】:

    • @karaszi 是的,订单丢失。注意脚本上方的文字。
    • 另外,在查找结果中用grep查找文件名不是很可靠;它可能匹配整个路径中的任何位置; +1 正确使用mktemp
    猜你喜欢
    • 1970-01-01
    • 2021-01-05
    • 2015-09-29
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多