使用 rm $(ls) 删除文件有什么缺点吗?

pos*_*ing 13 command-line delete files rm directory

我想知道使用rm $(ls)删除文件(或rm -r $(ls)删除目录)是否安全?因为在所有网站中,即使此命令看起来比其他命令容易得多,人们也会提供其他方法来执行此操作。

Den*_*nis 26

不,它不安全,常用的替代rm *方法也不是很安全。

很多问题rm $(ls)。正如其他人在他们的答案中已经涵盖的那样, 的输出ls将在内部字段分隔符中存在的字符处进行拆分。

最好的情况,它根本不起作用。最坏的情况是,您打算只删除文件(而不是目录)——或者有选择地删除一些文件-i——但是c -rf在当前目录中有一个同名的文件。让我们看看发生了什么。

$ mkdir a
$ touch b
$ touch 'c -rf'
$ rm -i $(ls)
$ ls
c -rf
Run Code Online (Sandbox Code Playgroud)

该命令rm -i $(ls)应该只删除文件并在删除每个文件之前询问,但最终执行的命令读取

rm -i a b c -rf
Run Code Online (Sandbox Code Playgroud)

所以它完全做了别的事情。

请注意,这rm *只是稍微好一点。与以前的目录结构一样,它将在这里按预期运行,但是如果您有一个名为 的文件-rf,您仍然不走运。

$ mkdir a
$ touch b
$ touch ./-rf
$ rm -i *
$ ls
-rf
Run Code Online (Sandbox Code Playgroud)

有几个更好的选择。最简单的只涉及rm和 globbing。

  • 命令

    rm -- *
    
    Run Code Online (Sandbox Code Playgroud)

    将完全按预期工作,其中--表示不应将其后的所有内容解释为选项。

    二十多年来,这一直是 POSIX 实用程序语法指南的一部分。它很普遍,但你不应该期望它无处不在。

  • 命令

    rm ./*
    
    Run Code Online (Sandbox Code Playgroud)

    使 glob 以不同方式扩展,因此不需要被调用实用程序的支持。

    对于我上面的示例,您可以看到最终将通过添加echo来执行的命令。

    $ echo rm ./*
    rm ./a ./b ./-rf
    
    Run Code Online (Sandbox Code Playgroud)

    前导./可防止rm意外地将任何文件名视为选项。


Ser*_*nyy 7

这是要做什么?

  • ls 列出当前目录中的文件
  • $(ls)替换ls作为参数的地方的输出rm
  • 本质上rm $(ls)是为了删除当前目录中的所有文件

这张图有什么问题吗?

ls无法正确处理文件名中的特殊字符。Unix 用户通常建议使用不同的方法。我还在一个关于计算文件名相关问题中展示了这一点。例如:

$ touch file$'\n'name                                                                                                    
$ ls                                                                                                                     
file?name
$ rm $(ls)
rm: cannot remove 'file': No such file or directory
rm: cannot remove 'name': No such file or directory
$ 
Run Code Online (Sandbox Code Playgroud)

此外,正如 Denis 的回答中正确提到的,带有前导破折号的文件名可以解释为rmafter 替换的参数,这违背了删除文件名的目的。

什么有效

您要删除当前目录中的文件。所以使用 glob rm *

$ ls                                                                                                                     
file?name
$ rm $(ls)
rm: cannot remove 'file': No such file or directory
rm: cannot remove 'name': No such file or directory
$ rm *
$ ls
$ 
Run Code Online (Sandbox Code Playgroud)

您可以使用find命令。这个工具经常被推荐用于不仅仅是当前目录 - 它可以递归遍历整个目录树,并通过-exec . . .{} \;

$ touch "file name"                                
$ find . -maxdepth 1 -mindepth 1                                                                                         
./file name
$ find . -maxdepth 1 -mindepth 1 -exec rm {} \;                                                                          
$ ls
$ 
Run Code Online (Sandbox Code Playgroud)

Python没有问题,文件名中使用特殊字符,这样我们就可以采用这种方法(注意,这只是一个是文件,则需要使用os.rmdir()os.path.isdir(),如果你想上的目录操作):

python -c 'import os; [ os.remove(i) for i in os.listdir(".") if os.path.isfile(i) ]'
Run Code Online (Sandbox Code Playgroud)

事实上,~/.bashrc为了简洁起见,上面的命令可以变成函数或别名。例如,

rm_stuff()
{
    # Clears all files in the current working directory
    python -c 'import os; [ os.remove(i) for i in os.listdir(".") if os.path.isfile(i) ]'

}
Run Code Online (Sandbox Code Playgroud)

Perl 版本将是

perl -e 'use Cwd;my $d=cwd();opendir(DIR,$d); while ( my $f = readdir(DIR)){ unlink $f;}; closedir(DIR)'
Run Code Online (Sandbox Code Playgroud)