удалите файлы и каталоги, но исключите все файлы из путей в текстовом файле

Согласно этому вопросу и ответу: удалите файл, но исключите все файлы в списке

Этот код делает точно, в чем я нуждаюсь, кроме него не работает над подкаталогами.

for i in *; do
    if ! grep -qxFe "$i" filelist.txt; then
        echo "Deleting: $i"
        # the next line is commented out.  Test it.  Then uncomment to removed the files
        # rm "$i"
    fi
done

Это, кажется, просто соответствует на тексте в текстовом файле, а не рассматривает каждую новую строку как путь. Так, когда текстовый файл содержит:

./leaveme.jpg
./i am staying.gif
./james/leaveme.gif
./james/

Это все еще пытается удалить james каталог? Это также игнорирует любые другие файлы в james каталоге, который должен быть удален.

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

Я также попробовал rsync:

rsync --dry-run -v -r --remove-source-files \
      --exclude-from='excludefile.txt' ./source ./to_delete

но если мой excludefile.txt похож на это:

./leaveme.jpg
./i am staying.gif
./james/leaveme.gif

пробный прогон говорит, что переместит./получаем каталогов, а также./source/james каталог? Очевидно, если я поместил./james в текстовый файл затем, он ничего не переместит в рамках того каталога, таким образом, это будет одно экстремальное значение к другому!

2
задан 14 January 2020 в 20:19

3 ответа

Предположим, ваш exclude.txt выглядит следующим образом:

leaveme.jpg
i am staying.gif
james/leaveme.gif

и все подкаталоги и файлы расположены в , один родительский каталог и ваш exclude.txt вместе с delete.sh находятся вне этого родительского каталога.

Приведенный ниже сценарий выполняет следующие действия:

  • Считывает имена файлов из exclude.txt построчно.
  • Найдите все совпадающие имена файлов в родительском каталоге и отметьте их, добавив к ним суффикс .KEEP .
  • Найдите в родительском каталоге все файлы, не отмеченные суффиксом .KEEP , и удалите их.
  • Найдите все пустые подкаталоги в родительском каталоге и удалите их.
  • Удалите суффикс .KEEP из сохраненных файлов, вернув им их исходные имена.

!!! ВНИМАНИЕ: ЭТО НЕ СУХОЙ ПРОБЕГ !!!

При запуске скрипт выполняет все указанные выше действия немедленно . Не запускайте его в своем фактическом каталоге, пока не протестируете его сначала, чтобы убедиться, что результаты соответствуют вашим ожиданиям.

Чтобы сначала протестировать сценарий, запустите его в поддельном каталоге копии, аналогичном по структуре и названию желаемому каталогу.

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

find "$path" -type f ! -name "*.KEEP" -exec rm {} \;

этой строкой:

find "$path" -type f ! -name "*.KEEP" -exec echo {} "Will be deleted!" \;

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


Чтобы создать и использовать сценарий, выполните следующие действия:

  1. Создайте и отредактируйте файл сценария в вашем домашнем каталоге и назовите его delete.sh , запустив следующую команду в терминале:

    nano ~ / delete.sh

  2. Скопируйте и вставьте следующий код в редактор, заменив / path / to / parent / directory / указав полный путь к каталогу, содержащему файлы, которые необходимо удалить, и заменив /path/to/exclude.txt на полный путь к вашему exclude.txt :

#!/bin/bash
path="/path/to/parent/directory/"
filelist="/path/to/exclude.txt"

while IFS=$'\n' read filename
        do
                mv -n "$path$filename" "$path$filename.KEEP"
        done < "$filelist"

find "$path" -type f ! -name "*.KEEP" -exec rm {} \;

find "$path" -type d -empty -delete

while IFS=$'\n' read filename
        do
                mv -n "$path$filename.KEEP" "$path$filename"
        done < "$filelist"


  1. Сохранить файл сценария и выйдите из редактора, нажав Ctrl + X , затем нажмите Y .

  2. Сделайте файл сценария исполняемым, запустив следующую команду в терминале:

    chmod + x ~ / delete.sh

  3. Запустите сценарий, выполнив следующую команду в терминале:

    bash ~ / delete .sh

Готово, в родительском каталоге остаются только файлы, перечисленные в exclude.txt .

0
ответ дан 14 January 2020 в 21:10

Можно использовать find . -type f перечислять все файлы рекурсивно с их полным путем. -type f опускает все каталоги и перечисляет только файлы. Но здесь filelist.txt должен содержать полные пути в файлы, которые мы должны исключить из удаления.

for i in $(find . -type f); do
    if ! grep -qxFe "$i" filelist.txt; then
        echo "Deleting: $i"
        # the next line is commented out.  Test it.  Then uncomment to remove the files
        # rm "$i"
    fi
done
0
ответ дан 14 January 2020 в 22:23

попытайтесь использовать rsync с помощью исключать опцию как следующее:

rsync --dry-run -v -r --remove-source-files \
      --exclude-from='/path/to/excludefile.txt' /path/to/source/ /path/to/somewhere/to_delete

примечания:

  • команда работает в --dry-run режим; удалите его для принятия реальных мер.
  • перед выполнением удостоверьтесь Ваш excludefile.txt расположен из /path/to/source путь, или добавляют себя к excludefile.txt файл для исключения этого также из удаления также.
  • rsync не может удалить пустые каталоги, если был кто-либо после завершенной операции, таким образом, Вы должны будете удалить их вручную, попробовать

    find /path/to/source -type d -empty -ok rmdir {} \;
    

    измените команду на ниже, если Вы не хотите, подтверждают для удаления для каждого каталога.

    find /path/to/source -type d -empty -delete
    
  • files&directories, которые Вы хотите, удаляют их, переместится в /path/to/somewhere/to_delete каталог, который Вы указали в команде; таким образом, можно легко перепроверить и удалить все.
0
ответ дан 14 January 2020 в 22:23

Другие вопросы по тегам:

Похожие вопросы: