Como excluir alguns arquivos do mecanismo de expansão de nome de arquivo no bash?

14

Eu tenho os diretórios do sistema de arquivos ubuntu no diretório raiz e copiei acidentalmente centenas de arquivos no diretório raiz.

Eu tentei intuitivamente remover os arquivos copiados, excluindo o sistema de arquivos como

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

mas não funciona. Qual é a maneira correta de excluir alguns diretórios enquanto exclui o todo?

Edição: Nunca tente qualquer um dos comandos aqui sem saber o que fazer!

Kenn
fonte
1
Qual shell você está usando? O globbing do nome do arquivo depende da casca quando se trata de fazer coisas sofisticadas como essa.
Kusalananda
2
Não é uma resposta, mas eu usaria por exemplo mc. Selecione tudo com e *, em seguida, desmarque arquivos específicos com a tecla -ou Insert.
Pbm
1
Você pode explicar o que é 'mc'?
Mikep
@Kusalananda it's/bin/bash
kenn
3
@ MikeP: mcé Midnight Commander, uma imitação muito útil do Norton Commander. É executado em um terminal. (Ambos Midnight Commander e Norton Commander são exemplos do que é chamado de um gerenciador de arquivos ortodoxa .)
AlexP

Respostas:

21

Desde que você está usando bash:

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

Eu recomendo adicionar echono início da linha de comando quando você estiver executando algo que potencialmente pode explodir o sistema inteiro. Remova-o se estiver satisfeito com o resultado.

Nota: O comando acima não removerá arquivos ocultos (aqueles cujo nome começa por um ponto). Se você também deseja removê-los, ative também a dotglobopção:

shopt -s dotglob
jimmij
fonte
Usei-o para limpar o sistema de arquivos com sucesso. No começo eu testei em um diretório. Eu também tentei rm -rf ./!(bin,sbin,..)vírgula separada, mas remove todos os diretórios.
Kenneth
Qual é essa !(...)sintaxe? A partir do exemplo, pensei intuitivamente ls ./!(*/)que listaria apenas arquivos, mas não funciona dessa maneira.
giusti
@giusti Essa sintaxe é uma combinação estendida de padrões no mecanismo de expansão de nome de arquivo - você encontrará sua descrição no manual do bash, no capítulo Expansão do nome do caminho. Ele não pode ser usado para excluir tipos de arquivos, apenas nomes, como com estrelas *ou outros globs.
jimmij
12

Este comando mostrará todos os não-diretórios em /:

find / -maxdepth 1 -type f

Depois de ter certeza absoluta de que não há arquivos que deseja manter, você pode usar:

find / -maxdepth 1 -type f -delete

Mais seguro, seria movê-los para outro lugar para garantir que você não esteja excluindo algo que deseja preservar:

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

Se, além dos arquivos, você também tiver diretórios adicionados à raiz do sistema de arquivos, isso pode ser automatizado excluindo os diretórios LSB de um sistema automatizado mvou rm, mas honestamente, já que estamos lidando com a remoção de coisas no diretório raiz do sistema de arquivos, sugiro fortemente que você considere fazê-lo manualmente, se possível.

Se isso não for viável, algo como isso poderia fazer o truque:

#!/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

Depois de passar no teste de grito (ou seja, seu sistema ainda funciona e você não está gritando de angústia), você pode remover o conteúdo de /root/preserve/.

Nota importante: Faça o que fizer, nem pense em executar qualquer permutação de rm -fr [ANYTHING GOES HERE] /.

DopeGhoti
fonte
sua solução exclui apenas arquivos, mas também existem pastas.
Kenn
1
Muitas vezes, ouvi gritos de consternação de pessoas mal-intencionadas rm. Como um script rm -fr $somepath/com somepathnão inicializado. Eu poderia ter ido mais longe ao expressar o quão grave isso é, mas optei por permanecer familiar em minha advertência.
DopeGhoti
3

Isso deve fazer o trabalho (embora não da mesma maneira que o OP solicita):

ls -1 >1.txt
pico 1.txt 

remova todos os arquivos / diretórios que deseja manter

xargs rm < 1.txt

Se todos os seus arquivos tiverem o mesmo formato de nome, data ou outra coisa, existem outros métodos.

Eu observaria os inodes - e veria se eles são sequenciais via ls -i | sort e, se são, os novos arquivos terão inodes maiores. Em seguida, usando o mesmo tipo de processo descrito acima ...

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

no comando recortar acima, verifique sua lista de inodes primeiro para garantir que seja a quantidade certa.

MikeP
fonte