如何在 Linux 中删除名称看起来只是一个连字符的文件,如“-”

jgr*_*tad 34 linux bash perl

我试过了

rm -- -
rm "-"
rm "\-"
rm \-
Run Code Online (Sandbox Code Playgroud)

给了 Perl 一个机会

~$ perl -e '$junk = glob("-"); chomp $junk; print "$junk\n"; `rm $junk`;'
-
rm: cannot remove `-': No such file or directory
Run Code Online (Sandbox Code Playgroud)

...和...

~$ perl -e '$junk = glob("-"); chomp $junk; print "$junk\n"; `mv $junk newfile.garbage`;'
-
mv: cannot stat `-': No such file or directory
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激,聪明的人。

wal*_*lyk 61

这曾经发布在 Unix 的 Usenet 常见问题解答中——我看到它在GNU 核心实用程序常见问题解答中。至少有五种不同的方法,但这很有效:

$ rm ./-
Run Code Online (Sandbox Code Playgroud)

如果文件名包含无法输入的字符,则使用:

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

-i标志要求确认每个文件是否应该删除。

  • rm -i * 也对我有用。谢谢沃利克! (2认同)

Kei*_*son 39

删除名称以 开头的文件-是常见问题解答,但看起来您遇到了不同的问题。

在您在问题中提到的解决方案中:

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

那应该工作。

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

这与rm -. 引号被 shell 剥离,rm命令只将单个连字符视为参数。引号对于转义 shell 元字符很有用;连字符是特殊的rm,而不是外壳。

rm "\-"
Run Code Online (Sandbox Code Playgroud)

引号对反斜杠进行转义,因此这会尝试删除名称由两个字符(反斜杠和连字符)组成的文件。

rm \-
Run Code Online (Sandbox Code Playgroud)

这就像rm "-",相当于rm -

碰巧的是,至少在 GNU coreutils 版本中rmrm -实际上删除(或尝试删除)名称仅包含一个连字符的文件。如果您的文件具有该名称,那么它现在已经消失了。我的结论是您的文件的名称看起来像一个连字符。

ls | cat -A
Run Code Online (Sandbox Code Playgroud)

应该对它的真正名称有所了解。

这是我刚刚拼凑起来的 Perl 脚本,它会提示您输入当前目录中的每个文件并询问是否将其删除。不提供保修,但我已经对其进行了简要测试。

#!/usr/bin/perl

use strict;
use warnings;

$| = 1;

opendir my $DIR, '.' or die ".: $!\n";
my @files = sort grep { -f $_ } readdir $DIR;
closedir $DIR;

foreach my $file (@files) {
    print "Remove $file? ";
    my $answer = scalar <>;
    if ($answer =~ /^[Yy]/) {
        unlink $file or warn "$file: $!\n";
    }
    elsif ($answer =~ /^[Qq]/) {
        exit 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:一个不太复杂的解决方案:如果文件名只是一个字符,那么rm ?应该将其删除(以及任何其他此类文件)。

  • `M-bM-^@M-^S` 是 Unicode“EN DASH”字符 0x2013 的 3 字节 UTF-8 表示的再现。我想知道您是否不小心从网页上复制并粘贴了它。 (13认同)
  • `rm -i *` 不起作用吗?似乎它会与 perl 脚本做同样的事情。 (7认同)
  • @RandalSchwartz:简洁得令人印象深刻(让我的大脑有点受伤)——但我想要 `/^y/i` 而不是 `/y/i`。毕竟,俄罗斯用户可能会输入“Nyet”。 (6认同)
  • perl -e 'unlink grep { 打印“删除 $_?”; &lt;标准输入&gt; =~ /y/i } glob "*"' (5认同)
  • 我猜它起源于我指向 wget 的网页。无论如何,再次感谢您的彻底解决方案!小心。 (2认同)

小智 19

如果你想要更安全的东西......

尝试使用 ls 和 find 的组合(这适用于您有权删除的任何文件)

'-i' 参数将为您提供每个目录条目的 inode 编号 ls -li

27 ----------  1 owner  group       3981 Oct 11 04:42 ?????
Run Code Online (Sandbox Code Playgroud)

一旦你有了 inode 号...

find . -inum **27** -exec rm -i {} \;
Run Code Online (Sandbox Code Playgroud)

  • +1 因为这是对这些问题的一个很好的一般答案。顺便说一句,在最近的查找中不需要使用 -exec rm,只需使用 -delete (2认同)
  • @Sirex - 我认为 `-exec rm -i {}` 的重点是提示删除的 `-i`。我正在查看“man find”,但看不到任何方法可以做到这一点。 (2认同)

Pet*_*y B 13

rm ./-一试。

-是开始一个标志参数标志。如果您以 a 以外的任何内容开头-,在这种情况下/,它将假定它是文件名。这是你想要的。

由于file./file是同一个文件,它将以名为-via的文件为目标./-

  • 与其输入 30 个字符,不如解释为什么 / 有助于正确解析更有用 (8认同)

小智 7

尝试:

$ ls -b
Run Code Online (Sandbox Code Playgroud)

查看文件名是否有不可打印的字符。


小智 7

不像大多数其他答案那样令人讨厌,但我会启动一个mc午夜指挥官的实例,然后选择并删除该文件。


run*_*rig 6

并不是说在这里使用 perl 是必要的,但这应该有效:

perl -e 'unlink "-"'
Run Code Online (Sandbox Code Playgroud)

或者看看上面的任何错误可能是什么:

perl -e 'unlink "-" or die "Err: $!"'
Run Code Online (Sandbox Code Playgroud)