从目录中删除所有文件,除了某些文件。

229

使用 sudo rm -r 命令时,如何删除除以下文件外的所有文件:

textfile.txt
backup.tar.gz
script.php
database.sql
info.txt

5
听起来像是需要在 http://unix.stackexchange.com/ 上问一个问题。 - Jason
1
有两种方式可以阅读这个问题,现有的答案涵盖了这两种解释:要么(a)保留位于目标目录中指定名称的文件,并且-如同rm -r所暗示的那样-删除其他所有内容,包括子目录-即使它们包含具有指定名称的文件;或者(b)遍历目标目录的整个子树,在每个目录中删除除列出名称的文件之外的所有文件。 - mklement0
2
对于所有在执行此操作的人,请务必先备份。我刚因为忘记排除.git而浪费了数天的工作时间,由于没有推送,我无法恢复超过30次提交。确保您排除了所有您关心的内容,包括隐藏文件夹。如果你要处理目录,请设置"-maxdepth 1"。 - Lonami
@Jason [删除除一个文件外的所有文件/目录 - Unix&Linux Stack Exchange](https://unix.stackexchange.com/q/153862/209677) - Pablo Bianchi
20个回答

4

尝试过以下方法:

rm -r !(Applications|"Virtualbox VMs"|Downloads|Documents|Desktop|Public)

但是带空格的名称总是很棘手。也尝试过使用Virtualbox\ VMs而不是引号。它总是删除那个目录(Virtualbox VMs)。

不适用于文件。rm !(myfile.txt)会删除所有内容,包括myfile.txt - khaverim
正如@pl1nk所指出的,首先应执行shopt -s extglob - zhuguowei
是的,在bash中激活扩展globbing(extglob)非常重要,我每天都会在几台实验室的Mac上进行此操作:shopt -s extglob 然后 cd /Users/alumno/ 最后 rm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library)在此处阅读有关扩展globbing的信息:https://www.linuxjournal.com/content/bash-extended-globbing - juanfal

4

只需:

rm $(ls -I "*.txt" ) #Deletes file type except *.txt

或者:

rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf

这不是推荐做法。解析 ls 命令的输出可能会成为一个问题。详细信息请参见此处 - R J

2

将文件设置为不可变的。即使是root用户也无法删除它们。

chattr +i textfile.txt backup.tar.gz script.php database.sql info.txt
rm *

所有其他文件都已被删除。
最终,您可以将它们重置为可变的。

chattr -i *

1

我相信你可以使用

rm -v !(filename)

除文件名外,该目录中的所有其他文件都将被删除,请确保在使用时。

使用以下命令,这个对我很有效。find . -type f ! -name 'filepattern' -print0 | xargs --null rm -f - Gowtam Thakur
此选项仅在启用extglob shell选项时才有效,即:$ shopt -s extglob。 - mrcrowl

0
这与@siwei-shen的评论类似,但你需要 -o 标志来处理多个模式。 -o 标志代表“或”。 find . -type f -not -name' * ignore1'-o -not -name' * ignore2'| xargs rm

0
我想要的答案是运行脚本,但我不想删除脚本本身。所以如果有人正在寻找类似的答案,请按照以下步骤操作。
创建一个.sh文件并编写以下代码:
    cp my_run_build.sh ../../ 
    rm -rf * cp  
    ../../my_run_build.sh . 
    /*amend rest of the script*/

0
你可以使用两个命令序列来完成这个操作。 首先,定义一个数组,包含你不想排除的文件名:
files=( backup.tar.gz script.php database.sql info.txt )

接下来,循环遍历要排除的目录中的所有文件,检查文件名是否在不想排除的数组中;如果不是,则删除该文件。

for file in *; do
  if [[ ! " ${files[@]} " ~= "$file"  ]];then
    rm "$file"
  fi
done

正则表达式比较不正确——它会保留任何文件名是受保护文件之一的子字符串(尽管周围的空格可以在一定程度上缓解这个问题;但文件名可能包含空格)。您应该收集所有文件的数组,然后从该数组中减去您要排除的文件,然后删除剩余的文件。 - tripleee

-1

由于还没有人提到这一点,在一个特定的情况下:

OLD_FILES=`echo *`
... create new files ...
rm -r $OLD_FILES

(或者只需使用rm $OLD_FILES)

或者

OLD_FILES=`ls *`
... create new files ...
rm -r $OLD_FILES

如果有些文件可能存在或不存在,您可能需要使用shopt -s nullglob

SET_OLD_NULLGLOB=`shopt -p nullglob`
shopt -s nullglob
FILES=`echo *.sh *.bash`
$SET_OLD_NULLGLOB

如果没有使用 nullglob,echo *.sh *.bash 可能会返回 "a.sh b.sh *.bash"。

(话虽如此,我个人更喜欢 this answer,尽管它在 OSX 上不起作用)


Leonardo Hermoso的现有答案可以更少出现错误地完成此操作。这将无法处理带有空格的文件名;使用一个数组优雅地解决了这个特定问题(并且不太重要地避免使用大写字母作为私有变量,通常应该避免这样做)。 - tripleee

-3
请勿直接执行命令,而是将所需文件移动到当前目录之外的临时目录。然后使用rm *rm -r *删除所有文件。
然后将所需文件移回当前目录。

在许多情况下,这可能不合适,因为要保留的文件正在被其他进程使用。如果要删除的文件只是一个小子集,并且涉及大量文件,则这也很麻烦。 - codeforester

-3

删除除了 file.name 以外的所有内容:

ls -d /path/to/your/files/* |grep -v file.name|xargs rm -rf

3
如果您的目录/文件名中有空格或不寻常的字符,这种方法会导致失败并可能造成数据丢失。您永远不应该解析ls命令。 https://mywiki.wooledge.org/ParsingLs - R J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接