我不小心粘贴到 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 个或多个字符)将无法匹配。
zsh
glob 没有问题,因为不构成字符一部分的字节被视为某种形式的特殊字符,而使用 bash glob 和当前版本,bash
当输入字符串无法解码为字符时,会切换到按字节匹配(使它的行为就像在 C 语言环境中一样)。
¹ 这次不限于常规的文件,还包括符号链接、fifos... 文件类型目录但是不会被删除,因为rm
除非您传递该选项,否则不会删除目录-r
。
² 您还可以使用-size 0
(其大小以 512 字节为单位为 0),这也可以在这里使用,因为大小是四舍五入的向上因此,就目前而言,一个字节大小的文件将被视为由一个 512 字节单元组成-size 0
,但更一般而言,为了精确大小匹配,我建议使用该c
后缀,例如-size 1
不适用于大小为 512 的文件,但适用于大小为 1 到 512 的文件。用于-size 512c
大小恰好为 512 的文件。对于zsh
的L
glob 限定符,默认单位是字节,不是 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
确保它仅匹配空文件。
或find
和mv
:
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
在删除备份之前查看看起来是否正常。