如何从目录中删除所有空文件?

如何从目录中删除所有空文件?

我不小心粘贴到 shell 中并创建了一堆空文件,这些文件全部命名为随机数。一次性消除所有这些的有效方法是什么?

目录下还有我需要的其他文件;它们中包含数字,但其中任何以数字开头的文件都是错误的。你能喜欢正则表达式删除吗?

答案1

您是说您要删除的文件是空的。删除这些文件的一种方法是仅删除空文件。这样,您就不会删除包含任何内容的文件。我相信这比按名称对它们进行分类更安全。从当前目录删除空文件的命令是:

find ./ -size 0 -delete

Stéphane Chazelas 提出了建设性意见。更好的命令是:

find ./ -maxdepth 1 -type f -size 0 -delete

答案2

zsh

rm -f -- *(.L0)

将删除常规的( .) 非隐藏空文件(L长度为 0)。

bash壳或其他壳:

zsh -c 'rm -f -- *(.L0)'

要删除名称仅由 ASCII 十进制数字组成的文件 1:

rm -f <->

where<-><x-y>匹配某个范围内但没有界限的数字。同样,对于其他 shell,您可以使用zsh -c '...'.

在 中bash,您还可以执行以下操作:

(shopt -s extglob failglob; rm -f +([0123456789])

或者在ksh93

rm -f ~(N)+([0123456789])

您可以将两者结合起来(删除全数字的空常规文件):

rm -f <->(.L0)

对于 POSIX shell 和实用程序,等效的内容是:

LC_ALL=C find . ! -name . -prune -type f -size 0c \
  ! -name '*[!0-9]*' -exec rm -f {} +

要查找全数字文件,我们会查找除包含至少一位非数字的文件之外的所有文件。-size 0c匹配大小为的文件字节² 为 0。

LC_ALL=C确保0-9范围仅包括 0123456789,而且也许更重要的是,如果文件名编码的字符集与语言环境不同,则该命令可以正常工作。例如,如果没有它,在 GNUfind和 UTF-8 语言环境中,一个名为$'St\xe9phane'Stéphane以 latin1 编码)的文件将被删除,而不是因为在其中找不到非数字(它仅由非数字组成),但因为它包含无法解码为字符的 0xe9 字节,所以*(匹配 0 个或多个字符)将无法匹配。

zshglob 没有问题,因为不构成字符一部分的字节被视为某种形式的特殊字符,而使用 bash glob 和当前版本,bash当输入字符串无法解码为字符时,会切换到按字节匹配(使它的行为就像在 C 语言环境中一样)。


¹ 这次不限于常规的文件,还包括符号链接、fifos... 文件类型目录但是不会被删除,因为rm除非您传递该选项,否则不会删除目录-r

² 您还可以使用-size 0(其大小以 512 字节为单位为 0),这也可以在这里使用,因为大小是四舍五入的向上因此,就目前而言,一个字节大小的文件将被视为由一个 512 字节单元组成-size 0,但更一般而言,为了精确大小匹配,我建议使用该c后缀,例如-size 1不适用于大小为 512 的文件,但适用于大小为 1 到 512 的文件。用于-size 512c大小恰好为 512 的文件。对于zshLglob 限定符,默认单位是字节,不是 512 字节单位。

答案3

您可以使用 glob。例如

echo rm [0-9]*

echo一旦您确认它不会删除您想要保留的任何内容,请将其删除。顺便说一句,如果您有rm别名rm -i(这是防止意外删除文件的一种非常常见的保护措施),您将需要通过运行command rm [0-9]*而不是仅覆盖它,否则您将为每个文件rm [0-9]*键入。y

或者,mv将文件放入新创建的目录中,将您想要保留的文件单独移回它们原来的位置,然后删除该目录。例如

mkdir /tmp/junk
mv [0-9]* /tmp/junk
cd /tmp/junk
# investigate and mv any you want to keep
cd -
rm -rf /tmp/junk

其他替代方案:

如果要删除的文件数量多于单个 bash 命令行所能容纳的数量:

for i in {0..9}; do rm "$i"*; done

或者

find . -maxdepth 1 -type f -empty -name '[0-9]*' -delete

或试运行版本:

find . -maxdepth 1 -type f -empty -name '[0-9]*' -print | less

-maxdepth 1选项防止 find 递归到子目录,并将-type f其限制为仅匹配常规文件(不是目录、套接字、命名管道等),并-empty确保它仅匹配空文件。

findmv

mkdir /tmp/junk
find . -maxdepth 1 -type f -empty -name '[0-9]*' -exec mv -t /tmp/junk/ {} +

(需要 GNUmv才能-t在要移动的文件列表之前指定目标目录的选项。GNU mv 是 Linux 上的标准)

答案4

如果您确定要删除所有以数字开头的文件,那么一种方法是使用 bashfor循环:

for n in [0-9]* ; do rm -i "${n}" ; done

我们循环遍历符合 shell glob [0-9]*(这意味着一个数字后跟一个或多个任意字符)的所有文件。对于每个文件(暂时称为$n,或为了安全起见“ ${n}”),我们删除它们 - 尽管我添加了 -i 进行交互,因为我对自动删除整个文件负载有点警惕。您可以自行决定删除此内容。

为了更加安全,您可以在删除之前检查每个文件以查看其是否为空:

for n in [0-9]* ; do if [[ `ls -l "${n}" |sed 's/[^ ]* [^ ]* [^ ]* [^ ]* \([0-9]*\) .*/\1/'` -eq 0 ]] ; then rm "${n}" ; fi ; done

因此,现在对于每个文件,我们通过sed替换来传输一个长列表,以用第五个字段(即文件大小)替换该行,并测试它是否等于 0。如果是,则应该可以安全地删除它,而无需在每个文件后说“是”。

这对我有用,但如果您要删除要保留的其他文件周围的大量文件,则可能值得从-i检查它是否选择了正确的文件开始。然后,当您感到舒服时,您可以Ctrl-C在没有-i.

或者备份目录,在一份副本上运行命令,并diff -r在删除备份之前查看看起来是否正常。

相关内容