Exclusão interativa de arquivos de uma lista

12

Gostaria de remover uma lista de arquivos e receber uma confirmação. A lista está no list.txtarquivo Por que o seguinte comando não funciona corretamente?

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

O comando anterior não espera por mim, mas felizmente nenhum arquivo é excluído.

Estou usando o Bash.

Francesco Turco
fonte

Respostas:

19

rm -ilê sua resposta da entrada padrão, que herda do whileloop. Portanto, uma linha de texto list.txtestá sendo usada como resposta para o "realmente remover?" questão. Para corrigir, você precisará separar as duas fontes de entrada. A maneira mais fácil é readobter 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, portanto rm, lerá o terminal conforme desejado.

Como alternativa, 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 xargs GNU:

xargs -rd '\n' --arg-file=list.txt rm -i --
chepner
fonte
1
Então, se eu tivesse na lista um arquivo chamado y, o arquivo anterior teria sido excluído?
Francesco Turco
5
Não apenas y, mas qualquer nome começando com y. Aparentemente, rmapenas olha para o primeiro caractere de qualquer resposta que recebe: 'y' é sim, qualquer outra coisa é não.
Chepner #
1

Para algo um pouco mais sofisticado do que responder sim ou não a cada arquivo, você pode usar iselecta seleção interativa baseada em ncurses. 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 lista baseada em nurses em tela cheia (terminal completo), onde os arquivos podem ser selecionados e desmarcados à vontade pressionando ESPAÇO. pressione ENTER para aceitar suas seleções (as entradas selecionadas serão impressas em stdout) ou qpara sair (nada impresso em stdout). pressione hpara obter ajuda.

Observe o echo rm- eu escrevi assim para testes. altere para apenas rmquando estiver confiante de que entende o que está fazendo.

Observe também que xargsestá sendo usado aqui \ncomo o separador de entrada. Isso não funcionará se algum dos nomes de arquivos tiver caracteres de avanço de linha. Por outro lado, iselecttambém não funcionará corretamente - ele espera um item por linha - infelizmente, iselectnão tem uma opção para entrada ou saída terminada em nulo.

iselectestá empacotado para debian, provavelmente ubuntu e outras distribuições também. A página inicial está em http://www.ossp.org/pkg/tool/iselect/

cas
fonte