Existe uma maneira simples de visualizar os arquivos que o rm removerá? [duplicado]

16

Existe uma maneira simples de avaliar o que um dado comando rm fará quando você não o entende (como não reconhecer como os sinalizadores, variáveis, etc. interagem)?

Embora ls ajude a detectar problemas em seus parâmetros rm , ls -abc XYZ não lista os mesmos arquivos que seriam afetados por rm -abc XYZ . Idealmente, gostaria de digitar algo como previewrm -abc XYZ e ver o que seria removido sem realmente remover nada, inclusive usando o sinalizador -f .

Eu quero essencialmente executar rm no modo de lote de teste. Ou seja, quero ver quais ações seriam necessárias se fossem executadas de forma real, de preferência sem tocá-las. Assim, testout 'rm -abc XYZ' pode ser o verdadeiro ideal.

    
por Dane 18.03.2014 / 23:16

5 respostas

4

A maneira simples é usar rm -i como descreve o @orion. Se você quer algo que não irá remover nada, mas não altera os flags do rm, você sempre pode construir sua própria versão de rm , vamos chamá-lo de preview-rm . É realmente muito simples, e você pode até mesmo fazer isso sem tocar nos arquivos de origem rm :

  1. Encontre a fonte na versão do seu sistema de rm . Você pode precisar baixar um pacote de código-fonte ou qualquer outra coisa. O GNU rm faz parte dos "principais utilitários" e consiste em dois arquivos C, rm.c e remove.c , além de vários arquivos de cabeçalho. Uma vez que você está pronto para compilar os utilitários do sistema, o resto é trivial.

  2. Crie o arquivo mockrm.c com o seguinte conteúdo. A única parte não trivial é que algumas versões de rm detectam diretórios tentando unlink() e verificando erros, portanto, precisamos garantir que isso funcione corretamente:

    #include <stdio.h>
    #include <sys/stat.h>
    #include <errno.h>
    
    int unlink(char *s)
    {
        struct stat sbuf;
        lstat(s, &sbuf);
        /* Simulate unlink error if we're asked to unlink a directory. */
        if (S_ISDIR(sbuf.st_mode)) {
            return EISDIR;
        }
    
        puts(s);
        return 0;
    }    
    
    int rmdir(char *d)
    {
      printf("%s (dir)\n", d);
      return 0;
    }
    
  3. Por fim, compile seu executável preview-rm assim:

    % cc rm.c remove.c mockrm.c -o preview-rm
    

    As funções em mockrm.c serão vinculadas em precedência às chamadas do sistema fornecidas pela biblioteca C, fornecendo um clone sem dentes de rm que você pode usar para visualização. (Teste se realmente funciona antes de apontar para arquivos importantes.)

Alternativa: se você estiver em um sistema que ofereça suporte ao LD_PRELOAD feature (OS X não), você pode conseguir o mesmo efeito compilando mockrm.c em uma biblioteca compartilhada ( .so ) e forçando para ser carregado pelo rm real:

% LD_PRELOAD=/path/to/mockrm.so rm -flags files

Mas, como você precisa alterar a invocação do comando, por que não criar um executável separado, como mostrado acima. Eu sei que seria um pouco nervoso apontar o verdadeiro rm em arquivos valiosos ( Editar: e se você atualizar seu sistema operacional, você teria que testar novamente e certificar-se de que rm hasn ' t mudou de uma maneira que desativou o wrapper.)

    
por 19.03.2014 / 17:33
29

Você pode usar rm -i para receber todos os arquivos que serão removidos. Você pode canalizar no para ele repetidamente, (confusamente) usando o comando yes , para apenas ver os prompts (rejeitando todos eles):

yes no | rm -i files/globs/options

EDIT em resposta aos comentários de @ user63051

Se você estiver preocupado com combinações de sinalizadores perigosos, é possível especificar rm -i -- e qualquer coisa depois disso NÃO será tratado como uma opção. Isso significa que, para que o -r flag funcione, você precisa colocá-lo antes de -- .

Outra sugestão, se você quiser tentar, é criar um usuário dummy que não pertença a nenhum dos grupos existentes. Se as permissões others de seus arquivos não incluírem a permissão write (elas normalmente não o fazem, a menos que você queira especificamente isso), basta fazer login como o outro usuário ( su dummy ) e fazer o comando rm . Não terá permissões para apagar nada, por isso simplesmente irá reclamar. Você também pode fazer isso para usar a sugestão acima (como proteção dupla).

Eu devo avisá-lo que todas as opções que chamam rm são um pouco perigosas. Eu costumo prefixar o comando inteiro que eu quero rodar com echo para ver quais argumentos serão dados ao comando (como ele expande os curingas e quais arquivos ele encontra). Em seguida, basta remover echo se tudo parecer bem. Observe que isso não listará o conteúdo de arquivos encontrados recursivamente com -r , mas você verá o diretório que deseja destruir.

Em essência - use echo se você quiser ver o que ele faz. Use -- para proteção contra bandeiras de fuga. Use -i apenas no caso, ele perguntará sobre cada arquivo e você notará se ele perguntar sobre algo que você não deseja remover. Somente se você realmente quiser produzir uma lista, um arquivo por linha, faz sentido fazer qualquer outra coisa.

    
por 18.03.2014 / 23:21
5

Quando eu quero fazer isso, eu uso 'find' como um wrapper em torno de rm. Isso é melhor (para o caso de uso que você tem em mente) porque:

  • É mais flexível em termos de correspondência de vários padrões
  • Ele pode manipular mais nomes de arquivos do que um caractere curinga de shell em subdiretórios ( / .tmp etc.)
  • Você pode fazer tudo que o rm pode fazer, já que envolve rm, mas mais além, como imprimir o comando rm inteiro.
  • Ele não chama rm com muita frequência, quando você usa + (em vez de;) como parte dos argumentos -exec, portanto, não é muito menos eficiente do que apenas executar o rm.

Para listar arquivos que você pode querer excluir:

find . -name \*.tmp

Para visualizar a exclusão:

find . -name \*.tmp -exec echo rm \{\} +

Para excluí-los, basta remover o 'echo':

find . -name \*.tmp -exec rm \{\} +

Ou, você pode fazer comandos mais avançados de pesquisa / exclusão, como este:

find . \( -name \*.tmp -o -iname cache -o -iname temp \) -exec rm \{\} +

Você também pode apenas canalizar a saída de find em "xargs rm", mas usar NULs para separar nomes de arquivos, da seguinte forma:

find . -name \*.tmp -print0 | xargs -0 rm
    
por 19.03.2014 / 10:07
4

Use a opção i . Veja man rm :

-i   prompt before every removal
    
por 18.03.2014 / 23:19
4

Se não estiver usando a opção -r , você poderá listar os arquivos com

ls -ld <parameters>

ou sua combinação favorita de ls opções, desde que inclua -d . A discrepância entre os argumentos da linha de comando e o que ls mostra é que, se um dos argumentos for um diretório, ls mostrará seu conteúdo.

Se você quiser apenas listar os nomes, echo <parameters> fará, ou se preferir em linhas separadas:

printf '%s\n' <parameters>

Esta lista é ambígua no caso de um nome de arquivo conter uma nova linha; isso é uma preocupação para o processamento automatizado, mas não quando você sabe que os arquivos não foram produzidos por uma parte potencialmente hostil.

Se estiver usando a opção -r , chame find para percorrer os diretórios recursivamente:

find <parameters>
    
por 19.03.2014 / 00:51

Tags