【问题标题】:Removing millions of files - oneliner删除数百万个文件 - oneliner
【发布时间】:2015-06-02 19:02:10
【问题描述】:

我想删除目录中的数百万个文件,并且页面提到以下 Perl 代码是最快的:

perl -e 'chdir "BADnew" or die; opendir D, "."; while ($n = readdir D) { unlink $n }`

但是,是否也可以仅对包含“排序”一词的文件执行此操作?有谁知道如何重写这个?

【问题讨论】:

  • 单线的魅力是什么?您可以通过删除换行符将几乎任何脚本转换为一行,但代码的可读性比一行代码更重要。
  • rm BADnew/*sorted* 不起作用的任何原因?
  • 您需要将 unlink $n 替换为对打开文件的函数的调用,查找您要查找的字符串 (sorted),关闭文件,然后调用 @987654325 @如果找到了这个词。不是很难;试试吧!
  • @PaulRoub:两个原因:有几百万个文件,所以参数列表会太长,因为文件包含sorted,而不是文件名。
  • 您是指内容包含单词sorted的文件还是名称包含单词sorted的文件?

标签: perl file unix rm


【解决方案1】:

可以使用find和grep组合来完成:

find BADnew -type f -exec grep -q sorted {} \; -exec rm {} \;

第二个-exec 命令只有在第一个返回码为零时才会执行。

你可以做空跑:

find BADnew -type f -exec grep -q sorted {} \; -exec echo {} \;

【讨论】:

  • 这样做的缺点是它必须创建数百万个进程,每个进程都执行单个文件的单个rm,这将使其非常慢。
  • 是的,确实如此——但这在很大程度上取决于包含关键字的文件数量——rm 的新进程将在匹配时创建。并且检查每个文件内容无论如何都会杀死 I/O。
  • c=0;forks_num=10;sleep_secs=3 找到 . -type f -exec grep -q 链接 {} \; -exec 回声 {} \; | { 同时读取 -r 文件;做 c=$((c+1)) ;测试 $c -eq "$forks_num" && sleep "$sleep_secs" && export c=0 ; ( echo "match: $file" )& 完成 }
  • 你读过 op 的问题吗?您是否尝试在包含 数百万 个文件的文件夹上运行它?这是行不通的。 find 在内存中建立一个列表。运行它会消耗所有内存,触发磁盘交换,从而破坏您的系统。
【解决方案2】:

核心模块File::Find会递归遍历所有子目录并对找到的所有文件执行子程序

perl -MFile::Find -e 'find( sub { open $f,"<",$_; unlink if grep /sorted/, <$f> }, "BADnew")'

【讨论】:

    【解决方案3】:

    试试:

    find /where -type f -name \* -print0 | xargs -0 grep -lZ sorted | xargs -0 echo rm
    #can search for specific ^^^ names                       ^^^^^^            ^^^^
    #                                   what should contain the file            |
    #                              remove the echo if satisfied with the result +
    

    以上:

    • find 搜索具有指定名称 (* - any) 的文件
    • xargs ... grep 列表文件包含字符串的内容
    • xargs rm - 删除文件
    • 不要死于“arg count too long”
    • 文件的名称中可能包含空格
    • 需要grep什么知道-Z

    也是一个变种:

    find /where -type f -name \* -print0 | xargs -0 grep -lZ sorted | perl -0 -nle unlink
    

    【讨论】:

      【解决方案4】:

      尽管有具体的问题,您还没有明确说明您是否需要文件 name 或文件 contents 包含sorted。这是两种解决方案

      首先,chdir 到您感兴趣的目录。如果您出于某种原因确实需要单行,那么将chdir 放入程序中是没有意义的。

      cd BADnew
      

      然后您可以取消链接所有作为文件且名称包含 sorted 的节点

      perl -e'opendir $dh, "."; while(readdir $dh){-f and /sorted/ and unlink}'
      

      或者您可以打开每个文件并阅读它以查看其内容是否包含sorted。我希望很明显,这种方法会慢得多,尤其是因为您必须阅读整个文件才能确定负数。请注意,此解决方案依赖于

      perl -e'opendir $dh, "."; while(readdir $dh){-f or next; @ARGV=$f=$_; /sorted/ and unlink($f),last while <>}'
      

      【讨论】:

        猜你喜欢
        • 2023-03-22
        • 2019-10-22
        • 2010-11-22
        • 1970-01-01
        • 2016-08-22
        • 2014-02-24
        • 2015-06-29
        • 2021-08-03
        • 1970-01-01
        相关资源
        最近更新 更多