Jak usunąć pliki wymienione w pliku tekstowym

23

Mam plik tekstowy z listą ścieżek do różnych plików. Czy mogę użyć polecenia, które będzie iterować po każdej linii i usunie plik pod podaną ścieżką?

daka
źródło

Odpowiedzi:

33

Użyj xargs:

xargs rm < file  # or
xargs -a file rm

Ale to nie zadziała, jeśli nazwy / ścieżki plików zawierają znaki, które należy usunąć.

Jeśli twoje nazwy plików nie mają nowych linii, możesz:

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

Alternatywnie możesz utworzyć następujący skrypt:

#!/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"

Zapisz jako /usr/local/bin/delete-from, udziel uprawnienia do wykonania:

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

Następnie uruchom go z:

delete-from /path/to/file/with/list/of/files
Eric Carvalho
źródło
2
Naprawdę czysta odpowiedź, ale catnie jest wymagana, możesz użyć stdinprzekierowania:< file xargs rm
koszmar
Dzieli nazwy folderów, a następnie ich szuka. Np. MÓJ FOLDER jest interpretowany jako „MÓJ” i „FOLDER”?
daka
@sudoman Odpowiedź zaktualizowana.
Eric Carvalho
Jeśli pliki nie mają spacji, możesz po prostu „rm - $ (plik kota)” w bash lub „rm - cat file” w (ba) sh lub csh.
szewc
@shooper catjest bezużyteczny , jak już wspomniano, skorzystaj z stdin! Spójrz na jego zaktualizowaną odpowiedź
Kos
20

Oto jeden ze sposobów radzenia sobie z nazwami plików z białymi znakami, odwrotnymi ukośnikami i innymi dziwnymi znakami:

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

To przeczyta każdy wiersz list.txt, zapisz go jako $filei uruchom rmna nim. W -rgwarantuje, że backslashe dosłownie czytać (tak, że \tdopasowuje \a t, a nie karta). W --zapewnia, że zajmuje się również nazwy plików zaczynające się -.

Możesz to również zrobić w Perlu:

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

Ten wczyta każdą nazwę pliku do %kskrótu, a następnie użyje unlinkdo usunięcia każdego z nich.

terdon
źródło
10

Poprzez python.

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

Zapisz powyższy skrypt w pliku o nazwie like, script.pya następnie uruchom skrypt, uruchamiając poniższe polecenie na terminalu.

python3 script.py file

file to plik wejściowy, w którym przechowywana jest ścieżka plików, które chcesz usunąć.

Avinash Raj
źródło
6
Ach, przynajmniej masz odwagę, aby opublikować odpowiedź na python :)
Jacob Vlijm
3

Głupie, ale oto jedno:

 tar -cvf /dev/null --remove-files -T filename
szewc
źródło
2

Inny sposób to zrobić:

Możesz „przygotować” plik, tworząc skrypt powłoki:

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

Jeśli twoje nazwy plików mogą zawierać pojedynczą cudzysłów ( '), możesz użyć tej nieco rozszerzonej wersji, aby uciec przed nimi:

$ 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'\'''

Możesz to uruchomić, przesyłając go do sh:

$ sed -E "s/'/'\\\''; s/^(.*)$/rm '\1'/" input_file | sh
Martin Tournoij
źródło
1

Jak rozumiem, masz plik tekstowy z plikami z pełnymi ścieżkami. Istnieją dwie możliwości:

  1. Twoja lista ma nazwy plików oddzielone znakami nowej linii, tzn. Każda linia ma pełną ścieżkę do pliku. w tym przypadku: oto proste wyjście:

    for i in $(cat listOfFiles.txt); do
        rm -f $i
    done
    
  2. Jeśli lista zawiera jeden lub więcej wierszy nazw plików oddzielonych spacjami lub tabulatorami, oto ćwiczenie:

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

    spowoduje to konwersję wszystkich białych znaków do nowych linii

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

Tak, istnieje wiele sposobów, aby to zrobić, ale jest to bardzo proste podejście.

Hopping Bunny
źródło