Bash -Циклический обход подкаталогов также включает файлы

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

for name in TestDir/*; do
    # the rest of the code
done

Чтобы проверить, встречается ли $nameв fileNames.txt, используйтеgrep -q:

for name in TestDir/*; do
    if ! grep -qxF "$name" fileNames.txt; then
        echo rm "$name"
    fi
done

-Fзаставляет grepвыполнять сравнение строк, а не сопоставление с регулярным выражением. С -qмы не получаем вывода из grep, только статус выхода, который мы можем использовать с оператором if(true, если строка была найдена, но восклицательный знак инвертирует смысл проверки ). -xсообщает grep, что строка $nameдолжна соответствовать всей строке от начала до конца, а не только части строки.

Я защитил настоящий rmс помощью echo. Запустите и убедитесь, что правильные файлы удаляются.

Если имена файлов указаны без пути TestDir, измените $nameв команде grepна${name##*/}:

for name in TestDir/*; do
    if ! grep -qxF "${name##*/}" fileNames.txt; then
        echo rm "$name"
    fi
done

Это будет искать часть имени файла пути в $name, а не полный путь, включая TestDir.

0
14.09.2020, 12:37
1 ответ

Я не совсем понимаю, в чем ваша проблема, ваш скрипт будет перебирать только каталоги. Это обеспечивается последним /в for dir in /var/log/fleet3/zok/*/. Однако у вас есть очень серьезная проблема, поскольку вы неправильно поняли конструкцию $(foo).

$(foo)выполнит команду fooи вернет результат. Например:

$ echo $(pwd)
/home/terdon

Кажется, вы хотите использовать переменную, а не выполнять ее, поэтому ваша cdкоманда должна быть:

cd "$dir"

А не cd $(dir).

Кроме того, если вы хотите удалить все подкаталоги /var/log/fleet3/zok/, вам не нужен цикл или скрипт, вы можете просто выполнить rm -rf /var/log/fleet3/zok/*/. Или,если вам просто по какой-то причине нужен цикл, вы можете упростить его до:

#!/bin/bash

for dir in /var/log/fleet3/zok/*/ ; do
    rm -rf "$dir"/*
done
3
18.03.2021, 23:05

Теги

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