Cómo eliminar archivos listados en un archivo de texto

23

Tengo un archivo de texto que tiene una lista de rutas a varios archivos. ¿Hay algún comando que pueda usar que recorra cada línea y elimine el archivo en la ruta indicada?

daka
fuente

Respuestas:

33

Uso xargs:

xargs rm < file  # or
xargs -a file rm

Pero eso no funcionará si los nombres / rutas de archivo contienen caracteres que se deben escapar.

Si sus nombres de archivo no tienen líneas nuevas, puede hacer:

tr '\n' '\0' < file | xargs -0 rm # or
xargs -a file -I{} rm {}

Alternativamente, puede crear el siguiente script:

#!/bin/bash

if [ -z "$1" ]; then
    echo -e "Usage: $(basename $0) FILE\n"
    exit 1
fi

if [ ! -e "$1" ]; then
    echo -e "$1: File doesn't exist.\n"
    exit 1
fi

while read -r line; do
    [ -n "$line" ] && rm -- "$line"
done < "$1"

Guárdelo como /usr/local/bin/delete-from, otorgue permiso de ejecución:

sudo chmod +x /usr/local/bin/delete-from

Luego ejecútalo con:

delete-from /path/to/file/with/list/of/files
Eric Carvalho
fuente
2
Respuesta realmente limpia, pero catno es obligatorio, puede usar la stdinredirección:< file xargs rm
kos
Es dividir los nombres de las carpetas y luego buscarlas. Por ejemplo, ¿MI CARPETA se interpreta como "MI" y "CARPETA"?
daka
@sudoman Respuesta actualizada.
Eric Carvalho
Si los archivos no tienen espacios, puede simplemente "rm - $ (archivo cat)" en bash o "rm - cat file" en (ba) sh o csh.
Shooper
@shooper no cates útil , como acabo de decir, ¡aprovecha stdin! Mire su respuesta actualizada
kos
20

Aquí hay una forma de tratar los nombres de archivos con espacios en blanco, barras diagonales invertidas y otros caracteres extraños:

while read -r file; do rm -- "$file"; done < list.txt

Eso leerá cada línea list.txt, la guardará como $filey se ejecutará rmen ella. Las -rasegura que las barras invertidas se leen literalmente (de modo que \tcoincide con una \y una ty no un TAB). El --asegura que también trata con nombres de archivos que comienzan con -.

También puedes hacer esto en Perl:

perl -lne '$k{$_}++; END{unlink for keys(%k)}' list.txt

Este leerá cada nombre de archivo en el %khash y luego lo usará unlinkpara eliminar cada uno de ellos.

terdon
fuente
10

A través de pitón.

import sys
import os
fil = sys.argv[1]
with open(fil) as f:
    for line in f:
        os.remove(line.rstrip('\n'))

Guarde el script anterior en un archivo llamado like script.pyy luego ejecute el script disparando el siguiente comando en la terminal.

python3 script.py file

file es un archivo de entrada donde se almacena la ruta de los archivos que realmente desea eliminar.

Avinash Raj
fuente
66
Ah, al menos tienes el coraje de publicar una respuesta en python :)
Jacob Vlijm
3

Tonto, pero aquí hay uno:

 tar -cvf /dev/null --remove-files -T filename
shooper
fuente
2

Otra forma de hacer esto:

Puede 'preparar' el archivo convirtiéndolo en un script de shell:

$ sed -E "s/^(.*)$/rm '\1'/" input_file
rm 'file1'
rm 'file2'
rm 'file with some spaces.ext'

Si sus nombres de archivo pueden tener una comilla simple ( '), puede usar esta versión ligeramente expandida para escapar de ellos primero:

$ sed -E "s/'/'\\\''; s/^(.*)$/rm '\1'/" input_file
rm 'file1'
rm 'file2'
rm 'file with some spaces.ext'
rm 'a file with "quotes"'
rm 'a file with '\''quotes'\'''

Y puede ejecutar esto canalizándolo a sh:

$ sed -E "s/'/'\\\''; s/^(.*)$/rm '\1'/" input_file | sh
Martin Tournoij
fuente
1

Según tengo entendido, tiene un archivo de texto con los archivos con las rutas completas. Hay dos posibilidades:

  1. Su lista tiene los nombres de archivo separados por nuevas líneas, es decir, cada línea tiene la ruta completa a un archivo. en este caso: aquí hay una salida simple:

    for i in $(cat listOfFiles.txt); do
        rm -f $i
    done
    
  2. Si su lista tiene una o más líneas de nombres de archivos separados por espacios o pestañas, entonces aquí está el ejercicio:

    sed -i 's/\s\+/\n/g' listOfFiles.txt
    

    esto convertirá todos los espacios en blanco en líneas nuevas

    for i in $(cat listOfFiles.txt); do
        rm -f $i
    done
    

Sí, hay muchas formas de hacerlo, pero este es un enfoque muy simple.

Saltando conejito
fuente