Как удалить файлы, перечисленные в текстовом файле


23

У меня есть текстовый файл со списком путей к различным файлам. Можно ли использовать команду, которая будет перебирать каждую строку и удалять файл по указанному пути?

Ответы:


33

Используйте xargs:

xargs rm < file  # or
xargs -a file rm

Но это не будет работать, если имена файлов / пути содержат символы, которые должны быть экранированы.

Если в ваших именах файлов нет перевода строки, вы можете сделать:

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

В качестве альтернативы вы можете создать следующий скрипт:

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

Сохраните как /usr/local/bin/delete-from, предоставьте разрешение на выполнение:

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

Затем запустите его с:

delete-from /path/to/file/with/list/of/files

2
Действительно чистый ответ, но catне обязательный, вы можете использовать stdinперенаправление:< file xargs rm
kos

Это разбивает имена папок вверх и затем ищет их. Например, МОЯ ПАПКА интерпретируется как «МОЯ» и «ПАПКА»?
Дака

@sudoman Ответ обновлен.
Эрик Карвалью,

Если в файлах нет пробелов, вы можете просто «rm - $ (cat file)» в bash или «rm - cat file» в (ba) sh или csh.
shooper

@shooper бесполезен cat, как только что было сказано, пользуйтесь stdin! Посмотрите на его обновленный ответ
Kos

20

Вот один способ, который может работать с именами файлов с пробелами, обратной косой чертой и другими странными символами:

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

Это будет читать каждую строку list.txt, сохранить его как $fileи запустить rmна нем. В -rгарантирует , что обратные косые читаются буквально (так что \tсоответствует \и , tа не TAB). В --гарантирует , что она также имеет дело с именами файлов , начиная с -.

Вы также можете сделать это в Perl:

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

Это будет читать каждое имя файла в %kхеш, а затем использовать unlinkдля удаления каждого из них.


10

Через питона.

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

Сохраните приведенный выше сценарий в файле с именем like, script.pyа затем выполните сценарий, выполнив приведенную ниже команду на терминале.

python3 script.py file

file это входной файл, в котором хранятся пути к файлам, которые вы действительно хотите удалить.


6
Ах, по крайней мере, у вас есть смелость, чтобы опубликовать ответ Python :)
Джейкоб Vlijm


2

Еще один способ сделать это:

Вы можете «подготовить» файл, сделав его сценарием оболочки:

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

Если ваши имена файлов могут иметь одинарную кавычку ( '), вы можете использовать эту слегка расширенную версию, чтобы сначала их избежать:

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

И вы можете запустить это, отправив по адресу sh:

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

1

Насколько я понимаю, у вас есть текстовый файл с файлами с полными путями. Есть две возможности:

  1. В вашем списке имена файлов разделены символами новой строки, то есть каждая строка имеет полный путь к файлу. в этом случае вот простой выход:

    for i in $(cat listOfFiles.txt); do
        rm -f $i
    done
    
  2. Если в вашем списке есть одна или несколько строк имен файлов, разделенных пробелами или табуляцией, то вот упражнение:

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

    это преобразует все пробелы в новые строки

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

Да, есть много способов сделать это, но это очень простой подход.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.