Eliminar interactivamente archivos de una lista

12

Me gustaría eliminar una lista de archivos y pedirme confirmación. La lista está en el list.txtarchivo. ¿Por qué el siguiente comando no funciona correctamente?

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

El comando anterior no me espera, pero afortunadamente no se elimina ningún archivo.

Estoy usando Bash

Francesco Turco
fuente

Respuestas:

19

rm -ilee su respuesta de la entrada estándar, que hereda del whilebucle. Entonces, ¿ list.txtse está utilizando una línea de texto como respuesta a la pregunta "realmente eliminar?" pregunta. Para solucionarlo, deberá separar las dos fuentes de entrada. La forma más fácil es readtomar su entrada de un descriptor de archivo 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

Ya no está redirigiendo la entrada estándar (fd 0) para el bucle while, por rmlo que leerá desde el terminal según lo desee.

Alternativamente, podrías haber hecho:

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

O, con GNU xargs:

xargs -rd '\n' --arg-file=list.txt rm -i --
chepner
fuente
1
Entonces, si tuviera en la lista un archivo llamado y, ¿el archivo anterior se habría eliminado?
Francesco Turco
55
No solo y, sino cualquier nombre que comience con y. Aparentemente, rmsolo mira el primer carácter de cualquier respuesta que reciba: 'y' es sí, cualquier otra cosa es no.
chepner
1

Para algo un poco más elegante que responder sí o no a cada archivo, puede usarlo iselectpara una selección interactiva basada en ncurses. p.ej

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

o para permitir la selección de archivos en el directorio actual:

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

Eso mostrará una lista basada en ncurses en pantalla completa (terminal completa), donde los archivos se pueden seleccionar y deseleccionar a voluntad presionando la barra espaciadora. presione ENTRAR para aceptar sus selecciones (las entradas seleccionadas se imprimirán en stdout) o qpara salir (nada impreso en stdout). Presione hpara obtener ayuda.

Tenga en cuenta que lo echo rmhe escrito así para probar. cámbielo a solo rmuna vez que esté seguro de comprender lo que está haciendo.

También tenga en cuenta que xargsse está utilizando aquí \ncomo separador de entrada. Esto no funcionará si alguno de los nombres de archivo tiene caracteres de salto de línea. Por lo demás, iselecttampoco funcionará correctamente (espera un elemento por línea). Desafortunadamente, iselectno tiene una opción para entrada o salida con terminación nula.

iselectestá empaquetado para debian, probablemente ubuntu y otras distribuciones también. La página de inicio está en http://www.ossp.org/pkg/tool/iselect/

cas
fuente