删除文件夹中除具有特定名称的文件夹外的所有文件夹


18

我需要使用日常脚本删除文件夹中的所有文件夹。需要保留当天的文件夹。

文件夹“ myfolder”具有3个子文件夹:“ test1”,“ test2”和“ test3”我需要删除除“ test2”以外的所有文件夹。

我正在尝试在此处匹配确切的名称:

find /home/myfolder -type d ! -name 'test2' | xargs rm -rf

要么

find /home/myfolder -type d ! -name 'test2' -delete

此命令也总是尝试删除主文件夹“ myfolder”!有办法避免这种情况吗?


6
在Unix和Linux中,我们称这些为“目录”,而不是“文件夹”。
tchrist

1
根据您的外壳,您可能需要引用该!运算符:\!'!'
Toby Speight '18

Answers:


32

这将删除其中的所有文件夹,./myfolder./myfolder/test2所有内容将保留:

find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' -delete

怎么运行的

  • find 启动查找命令。
  • ./myfolder告诉find从目录./myfolder及其内容开始。

  • -mindepth 1 不匹配./myfolder自身,仅匹配其下的文件和目录。

  • ! -regex '^./myfolder/test2\(/.*\)?' 告诉find排除(!)与正则表达式匹配的任何文件或目录^./myfolder/test2\(/.*\)?^与路径名的开头匹配。该表达式 (/.*\)?匹配(a)斜杠后跟任何东西,或(b)完全不匹配。

  • -delete 告诉find删除匹配(即不排除)的文件。

考虑一个看起来像的目录结构;

$ find ./myfolder
./myfolder
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

我们可以运行find命令(不带-delete)来查看其匹配的内容:

$ find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?'
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3

我们可以通过查看剩余的文件来验证此方法是否有效:

$ find ./myfolder
./myfolder
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

1
除了-prune保留test2/*/子目录之外,还可以选择:返回rm -r并添加-maxdepth 1
Toby Speight '18

@以撒好。做完了 (此外,+ 1是您的绝妙答案。)
John1024 '18

出色的工作!但遗憾:这将删除所有文件./myfolder。您只需要-type d目录缺少(IMvhO)。
NotAnUnixNazi

好的,这应该可以根据您的需要工作:find ./myfolder -depth -mindepth 1 -maxdepth 1 -type d ! -regex '^./myfolder/test2\(/.*\)?'
NotAnUnixNazi

10

使用bash

shopt -s extglob
rm -r myfolder/!(test2)/

例:

$ tree myfolder/
myfolder/
├── test1
│   └── file1
├── test2
│   └── file2
└── test3
    └── file3

$ echo rm -r myfolder/!(test2)
rm -r myfolder/test1 myfolder/test3
$ rm -r myfolder/!(test2)
$ tree myfolder/
myfolder/
└── test2
    └── file2

1 directory, 1 file

5

tl; dr

find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 \
     -exec echo rm -rf '{}' \;

如果对文件列表满意,请删除回显。


使用-mindepth 1将确保未选择顶层目录。

$ find ./myfolder -mindepth 1 -type d
./myfolder/test2
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

-not -name test2不会避免子目录里面test2

$ find ./myfolder -mindepth 1 -type d -not -name 'test2'
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

为此,您需要类似修剪的东西:

$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -print
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

不要使用delete,因为它暗示着depth,这将从最长的路径开始擦除:

$ find ./myfolder -depth -mindepth 1 -name test2 -prune -o -type d -print
./myfolder/test/a1/a2/a3
./myfolder/test/a1/a2
./myfolder/test/a1
./myfolder/test

两种使用方式rm -rfecho如果要实际擦除,请删除):

$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test
rm -rf ./myfolder/test/a1
rm -rf ./myfolder/test/a1/a2
rm -rf ./myfolder/test/a1/a2/a3

或者,还可以使用maxdepth是否需要删除目录(以及其中的所有内容)(删除echo即可删除):

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test

-delete如果目录不为空,A 仍然会失败:

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -delete
find: cannot delete ‘./myfolder/test’: Directory not empty

2

如果您使用的是zsh,则可以:

setopt extended_glob # if you don't have it enabled

rm -rf myfolder/^test2

0

用下面的命令测试,它工作正常

find  /home/myfolder -maxdepth 1 -type d ! -iname test2 -exec rm -rvf {} \;

您遇到了与OP相同的问题;在命令行上列出/ home / folder(没有critical -mindepth 1)使顶层目录符合所有条件(这是一个目录,并且没有命名为“ test2”),因此将其删除。
Jeff Schaller
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.