【问题标题】:Unix: How to delete files listed in a fileUnix:如何删除文件中列出的文件
【发布时间】:2011-02-28 13:13:08
【问题描述】:

我有一个长文本文件,其中包含要删除的文件掩码列表

例子:

/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php

我需要删除它们。试过 rm `cat 1.txt` 说列表太长了。

找到了这个命令,但是当我从列表中检查文件夹时,其中一些仍然有文件 xargs rm <1.txt 手动 rm 调用会从此类文件夹中删除文件,因此权限没有问题。

【问题讨论】:

  • 即使是六年后:您介意接受其中一个答案吗?这会将问题标记为已解决并帮助其他用户。

标签: linux unix


【解决方案1】:

这不是很有效,但如果您需要全局模式(如 /var/www/*),则可以使用

for f in $(cat 1.txt) ; do 
  rm "$f"
done

如果您没有任何模式并且确定文件中的路径不包含空格或其他奇怪的东西,您可以像这样使用 xargs:

xargs rm < 1.txt

【讨论】:

  • 如果路径包含空格,第一个解决方案(使用 CAT)会发生什么?
【解决方案2】:

假设文件列表在文件1.txt中,那么做:

xargs rm -r <1.txt

-r 选项导致递归到以1.txt 命名的任何目录。

如果任何文件是只读的,请使用-f 选项强制删除:

xargs rm -rf <1.txt

对执行编程删除的任何工具的输入要谨慎。 确定输入文件中指定的文件确实要删除。要特别小心看似简单的错别字。例如,如果您在文件及其后缀之间输入一个空格,它将看起来是两个单独的文件名:

file .txt

实际上是两个独立的文件:file 和 .txt。

这可能看起来不那么危险,但如果错字是这样的:

myoldfiles *

然后,您最终将删除当前目录中的myoldfiles 和所有 非点文件和目录,而不是删除所有以myoldfiles 开头的文件。可能不是你想要的。

【讨论】:

  • "myoldfiles /" 或 "/tmp" 使用 -rf 更加糟糕。注意“/”旁边的空格字符。
  • 我认为这是一个危险的答案,如果它是 文件 的列表,为什么要使用递归,再加上强制删除使这成为了一支枪
【解决方案3】:

使用这个:

while IFS= read -r file ; do rm -- "$file" ; done < delete.list

如果您需要全局扩展,您可以省略引用 $file:

IFS=""
while read -r file ; do rm -- $file ; done < delete.list

但请注意,文件名可能包含“有问题”的内容,我会使用不带引号的版本。想象一下文件中的这种模式

*
*/*
*/*/*

这会从当前目录中删除很多内容!我鼓励您以不再需要全局模式的方式准备删除列表,然后像我的第一个示例一样使用引用。

【讨论】:

  • 这是目前唯一可以处理所有/My Dir With Spaces//Spaces and globs/*.txt、--file-with-leading-dashes 的答案,而且它是 POSIX,适用于 GNU/Linux、macOS 和 BSD。
【解决方案4】:

你可以使用这个单行:

cat 1.txt | xargs echo rm | sh

Shell 扩展但执行rm 的次数最少。

【讨论】:

  • 只要展开不是太长?
  • 没错,一个 glob 可能会产生一个太长的参数列表——您可以将 -n &lt;n&gt; 参数添加到 xargs 以减少传递给每个 rm 的参数数量,但这仍然会不能保护您免受超出限制的单个 glob 的伤害。
【解决方案5】:

您可以使用 '\n' 将换行符定义为分隔符。

xargs -d '\n' rm < 1.txt

小心使用 -rf,因为如果 1.txt 包含带空格的路径,它可以删除您不想要的内容。这就是为什么新行分隔符更安全的原因。

在 BSD 系统上,您可以使用 -0 选项来使用换行符作为分隔符,如下所示:

xargs -0 rm < 1.txt

【讨论】:

  • 在 OS X 上这让我xargs: illegal option -- d
  • 好点。在 OS X 上似乎除了-0 之外别无选择。
  • xargs -I_ rm _ 也适用于 OS X :) 参见 stackoverflow.com/a/39335402/266309
  • 您也可以先运行xargs -d '\n' ls &lt; 1.txt 或xargs -d '\n' stat &lt; 1.txt 来验证将删除的内容并避免令人讨厌的意外
  • @Ray 使用 stat 或者如果文件不存在、您没有权限等会出现错误,我认为这有助于验证路径是否正确等
【解决方案6】:

xargs -I{} sh -c 'rm "{}"' &lt; 1.txt 应该做你想做的事。请小心使用此命令,因为该文件中的一个错误条目可能会导致很多麻烦。

这个答案是在@tdavies 指出原来没有做shell 扩展之后编辑的。

【讨论】:

  • 谢谢,但不需要删除文件夹,只删除文件
  • 球体不会被扩展,因为它们永远不会被外壳“看到”。
  • @tdavies 哇——你是对的。这个命令(虽然有点丑)可以工作:xargs -I{} sh -c 'rm {}' &lt; 1.txt
  • 如果文件名有单引号则不起作用
  • 编辑:现在也支持空格
【解决方案7】:

只是提供另一种方式,你也可以简单地使用下面的命令

$ cat to_remove
/tmp/file1
/tmp/file2
/tmp/file3
$ rm $( cat to_remove )

【讨论】:

  • 像魅力一样工作,同样适用于rm -r。以这种方式删除了大约 5TB 的数据。也可以与其他命令一起使用,例如ls 或du。
  • 带空格的路径呢?
【解决方案8】:

在这种特殊情况下,由于其他答案中提到的危险,我会

  1. 编辑例如Vim 和:%s/\s/\\\0/g,用反斜杠转义所有空格字符。

  2. 然后是:%s/^/rm -rf /,将命令放在前面。使用-r,您不必担心在其中包含的文件之后列出目录,使用-f,它不会因丢失文件或重复条目而抱怨。

  3. 运行所有命令:$ source 1.txt

【讨论】:

  • 空格不是唯一需要转义的字符,在文件名中流行的还有可能导致不必要的扩展的任何类型的括号。
【解决方案9】:

cat 1.txt | xargs rm -f | bash 运行命令将只对文件执行以下操作。

cat 1.txt | xargs rm -rf | bash运行命令会做如下递归行为。

【讨论】:

    【解决方案10】:

    这是另一个循环示例。这一个还包含一个“if 语句”作为检查条目是否为“文件”(或例如“目录”)的示例:

    for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done
    

    【讨论】:

      【解决方案11】:

      在这里,您可以使用 deletelist.txt 中的一组文件夹,同时避免一些模式

      foreach f (cat deletelist.txt)
          rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
      end
      

      【讨论】:

        【解决方案12】:

        这将允许文件名包含空格(可重现的示例)。

        # Select files of interest, here, only text files for ex.
        find -type f -exec file {} \; > findresult.txt
        grep ": ASCII text$" findresult.txt > textfiles.txt
        # leave only the path to the file removing suffix and prefix
        sed -i -e 's/:.*$//' textfiles.txt
        sed -i -e 's/\.\///' textfiles.txt
        
        #write a script that deletes the files in textfiles.txt
        IFS_backup=$IFS
        IFS=$(echo "\n\b")
        for f in $(cat textfiles.txt); 
        do 
        rm "$f"; 
        done
        IFS=$IFS_backup
        
        # save script as "some.sh" and run: sh some.sh
        

        【讨论】:

          【解决方案13】:

          如果有人更喜欢 sed 并删除 不带通配符扩展:

          sed -e "s/^\(.*\)$/rm -f -- \'\1\'/" deletelist.txt | /bin/sh
          

          提醒:在文件中使用绝对路径名或确保您位于正确的目录中。

          为了完整起见,awk:

          awk '{printf "rm -f -- '\''%s'\''\n",$1}' deletelist.txt | /bin/sh
          

          如果删除单引号,通配符扩展将起作用,但如果文件名包含空格,这很危险。这需要在通配符周围添加引号。

          【讨论】:

            猜你喜欢
            • 2016-11-25
            • 2013-01-12
            • 2019-04-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-10-29
            • 1970-01-01
            • 2016-02-17
            相关资源
            最近更新 更多