我有一个包含大量文件的目录。我想删除除file.txt之外的所有文件。

文件太多,无法单独删除不需要的文件,并且它们的名称种类繁多,无法使用*删除除该文件以外的所有文件。

有人建议使用

rm !(file.txt)


,但这不起作用。它返回:

Badly placed ()'s 


我的操作系统是Scientific Linux6。

有什么想法吗?

评论

移动您要保留的那一个,然后将其他人保留?

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

@shadur:好吧,我可以和他们联系:oneliners很有吸引力... ^^

谢谢,是的,我一直在寻找一种解决方案。保持移动文件太浪费时间了,因为我必须经常这样做。

#1 楼

POSIXly:

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


将除去file.txt之外的所有常规文件(递归包括隐藏文件)。要删除目录,请将-type f更改为-type d,并将-r选项添加到rm。 />(或调用bash

请注意,rm -- !(file.txt)仅适用于bash -O extglob和Korn Shell系列。并且使用extglob可能会导致bash错误。

rm -- !(file.txt)中,可以使用Argument list too long来取消启用了Extendedglob的模式:启用了选项zsh^kshbash具有相同的语法。

评论


指定目录是一种好习惯(在这种情况下为fullpath?或者在此处添加警告,该命令将从当前工作目录开始删除每个文件?)。我通常还会用rm作为回声rm来写任何示例,并要求人们仅在确实确定它将执行所需的操作时才取出回声。除此之外,+ 1代表彻底的答案

–奥利维尔·杜拉克(Olivier Dulac)
2014年9月5日9:00



我建议-delete而不是-exec,它更短并且更容易记住

–伊兹卡塔
2014年9月5日15:41

@Izkata:-delete未由POSIX定义。

–cuonglm
2014年9月5日15:42

如何排除文件列表?

– B Faley
2014年9月6日下午4:48

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

–mikeserv
2014年9月6日15:35



#2 楼

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

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)


评论


如果文件名带有空格,它将无法工作...

–马特奥
16年2月8日在16:07

Ciao @Matteo,它也适用于带有空格的文件,但是您需要在grep-pattern周围加上引号,例如ls | grep -v“带有spaces.bin的文件” | xargs rm。这是正常的grep语法。

–塞巴斯蒂安
16-2-8在19:14



@Sebastian问题不是grep,而是rm。 rm将获得由空格分隔的参数的列表。尝试触摸“ a b”;触摸“ cd”; ls | grep -v'a b'| xargs rm:您将得到rm:c:没有这样的文件或目录,rm:d:没有这样的文件或目录

–马特奥
16年2月9日在7:57

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

–StéphaneChazelas
16年8月30日在9:52

这对我有用ls -Q | grep -v file.txt | xargs rm -fr。 -Q开关是“将条目名称括在双引号中”

– Kuzyn
19年8月24日在13:11

#3 楼

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

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


一行:

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


但是需要一个支持here-strings的shell。

评论


这有点令人难以置信。

–vschum
2014年9月5日,下午2:36

@Derek-请查看编辑。

–mikeserv
2014年9月5日在2:49

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

–卡巴斯德
2014年9月5日在8:04

@kasperd-不仅当父外壳在运行rm和tar -x的时间之间死亡时。 rm可能会失败很多。

–mikeserv
2014年9月5日在8:05



@Derek-真的不是那么疯狂。 POSIX要求外壳程序在遇到此处文档时将其输入重定向到您指定的命令。必须先完成命令替换,然后再进行其他操作。大多数shell将临时文件用于here-docs-一些管道。两种方法都可以完成tar -c并在rm运行之前将shell存储其输出。因为rm结束时rm会忽略stdin的左尾标为tar -x,并且shell可以剥离其保存的文件副本的自身。在这里,文档经常可以像目标管道一样使用。

–mikeserv
2014年9月9日下午5:27



#4 楼

你们都太想了。

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/


评论


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

–mikeserv
2014年9月5日12:50



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

–约翰尼
2014年9月6日下午5:24

这绝对是最简单的答案。

– Ben Liyanage
16-10-18在23:10

如果fulldir是安装点,则两者都将失败。如果fulldir不是具有标准权限的“您的”目录,则两者都会导致设置不正确

–roaima
7月4日10:50

#5 楼

在我的Scientific Linux 6 OS上,它可以正常工作:

shopt -s extglob
rm !(file.txt)


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

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


评论


您的意思是我给的查找解决方案不起作用?

–cuonglm
2014年9月5日在2:30

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

–坎图拉
2014年9月5日在2:43



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

–cuonglm
2014年9月5日下午2:45

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

–坎图拉
2014年9月5日在2:55



哦,所以当然不行。 shopt不是tcsh内置的。

–cuonglm
2014年9月5日,下午3:15

#6 楼

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

评论


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

– terdon♦
2014年9月6日上午11:15

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

–詹姆斯·吉辛(James Jithin)
18年2月1日在18:27

#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


评论


如果./tmp已经作为文件存在,或者更糟的是,其中已经包含东西,则该怎么办?使用dirr = mktemp && mv file.txt“ $ dirr”; R M; mv“ $ dirr / *”。 && rm -rf“ $ dirr”可以避免此问题。

–乔
1月26日13:52

#8 楼

我发现这种方法非常简单,有效,并且不需要任何特殊的扩展(据我所知!)
ls --hide=file.txt | xargs -d '\n' rm


评论


你好老朋友

– ipatch
5月15日19:41

@ipatch恐怕您的名字没有立即响起?我想在哪里认识你?

– 2位
5月16日22:07

这只是互联网上的一个玩笑,当您重新访问已经完成的搜索并返回回答您已经投票赞成的时候。

– ipatch
5月16日22:21

user-images.githubusercontent.com/613805/…

– ipatch
5月16日22:22

好吧,只要有帮助。

– 2位
5月19日20:15