从父目录中除去一个目录及其后代以外的所有目录


8

目录结构

我想删除目录B和D。但是我想保留C及其所有后代文件和目录。删除父目录的所有子目录(一个目录及其子目录除外)的命令是什么?

帮助表示赞赏。


您要删除的目录是空的吗?
年长者极客


直接位于父目录(A在您的示例中)的文件呢?还要删除它们还是保留它们?
字节指挥官

Byte Commander问的是,A中是否有文件?还是只有目录?您要删除A中的常规文件还是只删除目录中的常规文件?
Sergiy Kolodyazhnyy,2016年

Answers:


6

您想要的是以下命令:

find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;

演示:

# List what's inside directory we want to remove
$ ls
file1  file2  keepMe/  removeA/  removeB/
# Testing what find gives without removing
$ find ~/TESTDIR -mindepth 1 -type d -not \( -name "keepMe" \)               
/home/xieerqi/TESTDIR/removeA
/home/xieerqi/TESTDIR/removeB
# Actual removal and testls
$ find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;
$ ls
file1  file2  keepMe/

说明:

  • find DIRECTORY 调用find命令以根据目录进行操作
  • -mindepth 1 :仅处理目录的内容,避免使用目录本身为0级
  • -maxdepth 1:防止降级到子目录(rm -rf无论如何都是递归的,因此我们不需要降级到子目录即可删除它们)
  • -type d :仅搜索目录
  • -not \( -name "keepMe" \) 忽略具有您要保留名称的项目
  • -exec rm -rf {} \; 对找到的每个项目执行删除

很好的解释。虽然对我来说击键太多...
Geek Elder 2013年

1
find是这里的好朋友,但Bash fortest是更好的朋友...>:-D
Byte Commander

8

使用bash shell的扩展glob功能(在当前的Ubuntu安装中默认启用),如下所示

$ tree A
A
├── B
├── C
│   ├── ac1
│   └── ac2
└── D

5 directories, 0 files

您可以C使用glob表达式(A/!(C)

$ echo A/!(C)
A/B A/D

因此,要删除目录C及其内容以外的所有内容,您只需使用

rm -rf A/!(C)

离开

$ tree A
A
└── C
    ├── ac1
    └── ac2

3 directories, 0 files

知道此功能真是太神奇了。语法错误附近意外的标记:线路1:在我ssh和手动运行,但我得到`“-bash它的伟大工程('",当我通过远程运行它ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)"。很多任何想法感谢。?
雷纳托·伽马

@renatoargh extglob仅对交互式shell启用了shell选项-不确定是否可以强制ssh执行此操作
steeldriver

5

一种简单的方法是使用trash-cli

你可以用安装 sudo apt-get install trash-cli

安装完成后,您可以使用导航到父目录A,cd /A然后发出命令 trash B D,其中B和D是您要删除的目录(它们最终将位于它们所在的驱动器的垃圾箱中,因此,如果您出错了,可以恢复文件)

在Ubuntu 16.04和14.04下测试


可以用类似的东西简化trash ! C吗?
Sergiy Kolodyazhnyy 2016年

@Serg Nope trash: cannot trash non existent !'`
极客长老

@Serg和C被捣毁了……
极客长老

找到它:stackoverflow.com/q/216995/3701431 它需要启用extglob
Sergiy Kolodyazhnyy 2016年

@Serg根据手头的工作可能会很有用!;-)
极客长老

4

只需使用Bash的for循环并test过滤所需的目录,然后使用rm -rf命令以递归方式删除目录,如下所示:

for x in /path/to/parent/*; do test "$x" != "dir_survive" && rm -rf "$x"; done

这会遍历其中的所有元素(文件和目录),/path/to/parent/并在其名称不等于时递归删除该元素dir_survive。如果父目录是当前目录,则只能写*为路径。

如果不确定并要测试哪些元素将首先被删除而不采取任何措施,只需将rm -rf上面命令中的替换为,echo它将仅输出删除的候选对象。

这是一个示例运行:

$ tree
.
├── dir1
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
├── dir2
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

9 directories, 12 files

$ for x in *; do test "$x" != "dir_survive" && rm -rf "$x"; done

$ tree
.
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

3 directories, 4 files
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.