Excluindo interativamente arquivos de uma lista

12

Gostaria de remover uma lista de arquivos e ser solicitado a confirmar. A lista está no arquivo list.txt . Por que o seguinte comando não funciona corretamente?

while read i; do rm -i $i; done < list.txt

O comando anterior não me espera, mas felizmente nenhum arquivo foi apagado.

Estou usando o Bash.

    
por Francesco Turco 02.10.2012 / 19:35

2 respostas

19

rm -i lê sua resposta da entrada padrão, que é herdada do loop while . Então, uma linha de texto de list.txt está sendo usada como a resposta para o "remover realmente?" questão. Para corrigir, você precisará separar as duas fontes de entrada. A maneira mais fácil é ter read recebendo sua entrada de um descritor de arquivo separado:

while IFS= read <&3 -r i; do
  rm -i -- "$i"     # Quote the file name, not just to be safe,
                    # but because it's the right syntax.
done 3< list.txt

Você não está mais redirecionando a entrada padrão (fd 0) para o loop while, então rm lerá do terminal como desejado.

Alternativamente, você poderia ter feito:

IFS=$'\n' # set field separator to newline
set -f    # disable globbing upon command substitution
rm -i -- $(cat list.txt)

Ou, com GNU xargs:

xargs -rd '\n' --arg-file=list.txt rm -i --
    
por 02.10.2012 / 19:44
1

Para algo um pouco mais sofisticado do que responder sim ou não a cada arquivo, você pode usar iselect para a seleção baseada em ncurses interativos. por exemplo,

iselect -a -m < list.txt | xargs -d '\n' -r echo rm 

ou para permitir a seleção de arquivos no diretório atual:

find . -maxdepth 1 -type f | iselect -a -m | xargs -d '\n' -r echo rm

Isso exibirá uma listagem baseada em ncurses de tela inteira (terminal completo), na qual os arquivos podem ser selecionados e desmarcados à vontade, pressionando-se ESPAÇO. pressione ENTER para aceitar suas seleções (as entradas selecionadas serão impressas no stdout) ou q para sair (nada é impresso no stdout). pressione h para ajuda.

Observe o echo rm - escrevi assim para testes. mude para apenas rm quando tiver certeza de que entende o que está fazendo.

Observe também que xargs está sendo usado aqui com \n como o separador de entrada. Isso não funcionará se algum dos nomes de arquivo tiver caracteres de alimentação de linha. Para esse assunto, o iselect também não funcionará corretamente - ele espera um item por linha - infelizmente, iselect não tem uma opção para entrada ou saída terminada com nulo.

iselect é empacotado para o debian, provavelmente para o ubuntu e outras distros também. home page está em link

    
por 03.10.2012 / 00:50