如何从bash的文件名扩展机制中排除某些文件?


14

我在根目录中有ubuntu文件系统目录,而我不小心将数百个文件复制到了根目录中。

我直觉地试图通过排除文件系统来删除复制的文件,例如

rm -rf !{bin,sbin,usr,opt,lib,var,etc,srv,libx32,lib64,run,boot,proc,sys,dev} ./.

但它不起作用。在删除整个目录时排除某些目录的正确方法是什么?

编辑:切勿在不知所措的情况下尝试此处的任何命令!


1
您正在使用什么外壳?当进行类似这样的操作时,文件名的浮动取决于外壳程序。
Kusalananda

2
没有答案,但是我将使用例如mc。使用选择所有内容*,然后使用-Insert键取消选择特定文件。
pbm

1
您能解释一下“ mc”是什么吗?
MikeP

@Kusalananda,这是/bin/bash

3
@MikeP:mc是Midnight Commander,是Norton Commander的非常有用的模仿。它在终端中运行。(Midnight Commander和Norton Commander都是所谓的正统文件管理器的示例。)
AlexP

Answers:


21

由于您正在使用bash

shopt -s extglob
echo rm -rf ./!(bin|sbin|usr|...)

我建议echo您在运行某些可能会使整个系统崩溃的内容时在命令行的开头添加。如果对结果感到满意,请将其删除。

注意:上面的命令不会删除隐藏的文件(名称以点开头的文件)。如果您也要删除它们,请同时激活以下dotglob选项:

shopt -s dotglob

我用它成功清理了文件系统。首先,我在目录中对其进行了测试。我还尝试了rm -rf ./!(bin,sbin,..)逗号分隔,但它删除了所有目录。
肯恩

那是什么!(...)语法?从该示例中,我直觉上认为ls ./!(*/)仅列出文件,但这种方式行不通。
giusti

@giusti此语法是文件名扩展机制中的扩展模式匹配-您可以在bash手册的“路径名扩展”一章下找到其说明。它不能用于排除文件的类型,只能排除名称,就像使用星号*或其他glob一样。
jimmij

12

此命令将显示以下目录中的所有非目录/

find / -maxdepth 1 -type f

一旦你取得了绝对确保没有文件是那里,你想保留,您可以使用:

find / -maxdepth 1 -type f -delete

更安全的做法是将它们移到其他位置,以确保您不会删除要保留的内容:

mkdir /root/preserve
find / -maxdepth 1 -type f -exec mv -- "{}" /root/preserve/\;

如果,除了文件,你也有目录,您已经添加到文件系统的根,这可以排除从自动LSB的目录中自动mvrm,但说实话,因为我们正在处理的事情清洗文件系统的根目录,强烈建议您考虑在可行的情况下手动进行操作。

如果这不可行,则可以执行以下操作:

#!/bin/bash
declare -a excludes
for item in root sys 'lost+found' mnt home proc etc opt boot lib lib64 libx32 sbin media srv dev var usr bin tmp run; do
    excludes+=("$item")
done
if ! [[ -d /root/preserve ]]; then
    mkdir -p /root/preserve
fi
IFS="\n"
for item in find / -type d -maxdepth 1; do
    really=true
    for exclude in ${excludes[@]}; do
        if [[ "$exclude" == "${item#/}" ]]; then
            really=false
        fi
    done
    if [[ "true" == "$really" ]]; then
        mv -- "$item" /root/preserve/
    fi
done

通过尖叫测试后(即系统仍在运行并且您没有痛苦地尖叫),可以删除的内容/root/preserve/

重要说明:无论您做什么,都不要考虑运行的任何排列rm -fr [ANYTHING GOES HERE] /


您的解决方案仅删除文件,但周围也有文件夹。
肯恩

1
我听过太多次了,一个目标不佳的人感到沮丧rm。就像其中rm -fr $somepath/包含somepath未初始化的脚本。我本来可以表达这有多严重,但在我的劝告下,选择保持家庭友好。
DopeGhoti

3

这样就可以完成工作(尽管与OP要求的方式不同):

ls -1 >1.txt
pico 1.txt 

删除您要保留的所有文件/目录

xargs rm < 1.txt

如果您的文件都具有相同的名称格式,日期或其他名称,则可以使用其他方法。

我将查看inode-并通过ls -i | sort查看它们是否连续,如果是,那么新文件将具有更大的inode。然后使用与上述相同的过程类型...

ls -iF1 | sort |cut -c10- | grep -vE "\/|\@" >i.txt   #This part removes entries that are not regular files, such as directories and links.  
pico i.txt
xargs rm < i.txt

在上面的cut命令中,首先检查您的inode列表以确保其数量正确。

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.