删除除一个文件外的所有文件/目录


243

我有一个包含大量文件的目录。我想删除除file.txt之外的所有文件。我该怎么做呢?

有太多文件无法单独删除不需要的文件,并且它们的名称种类繁多,无法使用*删除所有文件(除了一个文件)。

有人建议使用

rm !(file.txt)

但这是行不通的。它返回:

Badly placed ()'s 

我的操作系统是Scientific Linux 6。

有任何想法吗?


13
移动您要保留的那一个,然后再删除其他人?
Olivier Dulac 2014年

5
@OlivierDulac我们是这个问题中唯一没有过分考虑问题的两个人吗?
Shadur

1
@shadur:好吧,我可以和他们联系:单线纸很有吸引力……^^
Olivier Dulac

1
谢谢,是的,我一直在寻找一种解决方案。保持移动文件太浪费时间,因为我经常这样做。
坎图拉2014年

Answers:


287

POSIXly:

find . ! -name 'file.txt' -type f -exec rm -f {} +

将删除除以外的所有常规文件(递归包括隐藏文件)file.txt。要删除目录,请更改-type f为,-type d然后向添加-r选项rm

在中bash,要使用rm -- !(file.txt),必须启用extglob

$ shopt -s extglob 
$ rm -- !(file.txt)

(或致电bash -O extglob

请注意,extglob仅适用于bash和Korn Shell家族。并且使用rm -- !(file.txt)会导致Argument list too long错误。

在中zsh,您可以使用^否定已启用Extendedglob的模式:

$ setopt extendedglob
$ rm -- ^file.txt

或使用带有kshbash带有选项ksh_globno_bare_glob_qual启用的相同语法。


9
指定目录是一种好习惯(在这种情况下为fullpath?或者在此处添加警告,该命令将从当前工作目录开始删除每个文件?)。我通常也用rmas echo rm代替任何示例,并要求人们仅在确实确定它将执行所需的操作时才取出回声。除此之外,您需要+1才能获得完整答案
Olivier Dulac 2014年

11
我建议-delete,而不是-exec更短,更容易记住
Izkata

6
@Izkata:-deletePOSIX未定义。
cuonglm 2014年

5
如何排除文件列表?
Meysam 2014年

5
@Meysam-请参阅我的答案以获取将处理文件列表的解决方案。除此之外,find您还可以使用Gnouc的解决方案! \( -name one_file -o -name two_file \)等等。
mikeserv 2014年

112

另一个方向不同(如果文件名中没有空格)

ls | grep -v file.txt | xargs rm

或(即使文件名中有空格也可以)

ls | grep -v file.txt | parallel rm

来自man grep

 -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v is specified by POSIX)

2
如果文件名带有空格,它将不起作用...
Matteo

1
Ciao @Matteo,它也适用于带有空格的文件,但是您需要在grep-pattern周围加上引号,例如ls | grep -v "a file with spaces.bin" | xargs rm。这是正常的grep语法。
塞巴斯蒂安

1
@Sebastian问题不是grep而是rmrm将获得由空格分隔的参数的列表。试试touch 'a b'; touch 'c d'; ls | grep -v 'a b' | xargs rm:您会得到rm: c: No such file or directoryrm: d: No such file or directory
Matteo

1
是的,这是一个普遍的问题。看到的选项-print0find-0xargs。这是一种解决方法,但略有不便。find . -maxdepth 1 -type f | grep -v 'a b' | tr '\n' '\0' | xargs -0 rm。顺便说一下,gnu parallel处理得很好(我几乎总是用它代替xargs:ls | grep -v 'a b' | parallel rm
Sebastian

1
它不仅是空格,全是空格和换行符,而且还要引号字符(单引号,双引号和反斜杠)和以开头的文件名-
斯特凡Chazelas

32

维护副本,删除所有内容,恢复副本:

{   rm -rf *
    tar -x
} <<TAR
$(tar -c $one_file)
TAR

一行:

{ rm -rf *; tar -x; } <<< $(tar -c $one_file)

但这需要支持here-strings的shell。


10
这有点令人难以置信。
vschum 2014年

2
@Derek-请查看编辑。
mikeserv

2
但是,如果此过程在中途中断,或其他任何错误,则文件已消失。
kasperd 2014年

2
@kasperd-不 只有当父shell时之间死亡运行rmtar -xrm可能会失败很多。
mikeserv

2
将其移至另一个目录并移回目录是否更有效?我们不需要处理文件的内容,而只需要处理其路径。
leonbloy 2014年

23

你们都在想这个。

cd ..
mv fulldir/file.txt /tmp/
rm -rf fulldir
mkdir fulldir
mv /tmp/file.txt fulldir/

做完了

编辑实际上,更容易:

cd ..
ln fulldir/file.txt ./
rm -rf fulldir
mkdir -p fulldir
mv file.txt fulldir/

3
我的回答也是一样。exce [pt它不会对该目录失去任何权限。
mikeserv

6
如果它是与/ tmp分开的文件系统上的一个大文件,并且您正尝试从文件系统的根目录中删除所有内容,那么将其移到安全的位置可能不是一种选择。
约翰尼2014年

1
这绝对是最简单的答案。
Ben Liyanage

17

在我的Scientific Linux 6操作系统上,此方法有效:

shopt -s extglob
rm !(file.txt)

我还在虚拟机上安装了Debian 32bit。上面的方法不起作用,但是下面的方法可以起作用:

find . -type f ! -name 'file.txt' -delete

1
您的意思是find我给的解决方案不起作用?
cuonglm

“无效”或“无效”。是的,您的查找解决方案也可以。谢谢。
坎图拉2014年

1
您可以提供更多详细信息吗?“怎么不起作用?它不会删除其他文件,或者它已删除file.txt或其他任何东西?”
cuonglm 2014年

我的意思是在Debian OS上,“ $ rm!(file.txt)”返回“ Badly Place()'s”。因此,我尝试了“ $ shopt -s extglob”,但返回:“ shopt:找不到命令”。然后,我尝试了“查找”解决方案。确实有效。
Kantura 2014年

1
哦,所以当然不行。shopt不是tcsh内置的。
cuonglm 2014年

10

使用rm !("file.txt")代替rm !(file.txt)


4
那绝对没有任何区别。这里的问题是OP是1)不使用支持这种格式的外壳,2)即使在bash中,也需要使用启用它shopt -s extglob。无论如何,引用这样的简单文件名不会有任何区别。
terdon

1
要保留utils文件夹,请执行-rm -rf!(“ utils”)
James Jithin,

7

只是给出一个不同的答案,您可以使用rm它不会删除文件夹的默认行为:

mkdir tmp && mv file.txt tmp  # create tmp dir and move files there
rm                            # delete all other files
mv tmp/* . && rm -rf tmp      # move all files back and delete tmp dir

1

我发现这种方法非常简单,有效,并且不需要任何特殊的扩展(据我所知!)

ls --hide=file.txt | xargs rm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.