Удалите папки, которые не соответствуют списку

Создание ответов выше чиновника: да, это работает. Много людей делает точно это (самостоятельно включенный), но существует включенная кривая обучения.

6
22.03.2015, 17:29
7 ответов

Резервное копирование с помощью gzip выполняется не в каталог, а в другой файл:

 gzip < file.in > file.out

или в вашем случае:

 filelocation=/home/user/image.img
 backuplocation=/home/image.img.gz
 gzip < "$filelocation" > "$backuplocation"

на основе этого можно сделать:

 gunzip < "$backuplocation" > /some/new/location/image.img
-121--16â1-

U-Boot делает именно то, что должно (замалчивая вывод) с помощью следующей команды:

# define CONFIG_EXTRA_ENV_SETTINGS\

  "silent = 1\0

кажется, что это происходит только в моей системе.

-121--60988-

При условии, что имена файлов не содержат :\[ *? , можно использовать GLOBIGNORE . Просто отформатируйте список каталогов соответствующим образом. Например:

$ cat names.txt
folder1
folder3

Это очень легко преобразовать в двоеточие разделенный список:

$ paste -s -d : names.txt
folder1:folder3

Так что теперь вы можете установить, что в качестве значения GLOBIGNORE:

GLOBIGNORE=$(paste -s -d : ../names.txt)

И приступить к их удалению нормально:

rm -r -- *

Я только что протестировал это на Linux с 300 каталогами и он работал идеально.

5
27.01.2020, 20:22

Простой подход - это список всех файлов и игнорировать те, которые находятся в файле списка. Обратите внимание, что я организующуюся для переменной IGNORE_LIST , чтобы начать и заканчиваться новой строкой, чтобы я мог проверить, включен ли $ x простым способом (просто проверяя, что IGNORE_LIST содержит $ x не работает, поскольку он также будет соответствовать файлам, имя которого представляет собой подстроку элемента списка игнорирования).

newline='
'
ignore_list="$newline$(cat list.txt)$newline"
cd target_folder
for x in * .[!.]* ..?*; do
  case "$x" in *"$newline"*) continue;; esac   # sanity check: if the file name contains a newline, leave it alone
  case "$ignore_list" in
    *"$newline$x$newline"*) echo "Skipping $x";;
    *) rm -rf -- "$x";
  esac
done
2
27.01.2020, 20:22

Как насчет этого?

find ./target_folder/ \
    -mindepth 1 \
    -maxdepth 1 \
    -type d \
    -not -name 'anything[0-9]*' \
    -exec rm -rf {} \;

Позвольте мне объяснить:

  • -Mindepth 1 гарантирует, что вы не совпадаете ./ TAVE_FOLDER /
  • -MAXDEPTH 1 гарантирует, что вы не соответствуете любым подпапкам.
  • -Type d говорит найти только для матча каталогов, а не файлов.
  • -NOT -NAME 'НИЧЕГО [0-9] * « исключает из шаблона все, что соответствует шаблону. Довольно очевидно, что один.
  • --eexec должен использоваться с осторожностью, особенно когда он включает в себя ​​RM . Вы должны всегда тестируйте это, используя ECHO , прежде чем идти вперед и RM -RF Thanging так. Найти Может быть сложно к
  • Не забывайте трейлинг \; при использовании EXEC.

Вы можете прочитать найти ручную страницу для получения дополнительной информации. Это очень удобно инструмент .

2
27.01.2020, 20:22

Вы можете сделать это в Bash, как

for folder in /target_folder/*/
do
    folder=${folder%/}
    if ! grep -qx "${folder##*/}" folders_list.txt
    then
        rm -rf "$folder"
    fi
done
1
27.01.2020, 20:22

С zsh (обратите внимание, что GLOBIGNORE не зависит от bash, ни bash , ни zsh установлены во FreeBSD по умолчанию, но доступны оба):

(cd /target_folder || exit
all_dirs=(*(/))
to_exclude=(${(f)"$(<names.txt))"})

rm -rf -- ${all_dirs:|to_exclude})

Особые особенности zsh :

  • * (/) . (/) - квалификатор glob , который означает выбор только файлов типа в каталоге .
  • $ (: расширяется до содержимого (без завершающих символов новой строки) файла (происходит из ksh , bash также он есть, но выполняет форк для чтения содержимого файла там).
  • $ {(f) ...} . Это флаг раскрытия параметра , который разделяет раскрытие «$ (...)» на перевод строки. Для bash вам нужно будет сделать что-то вроде: IFS = $ '\ n'; set -f; to_exclude = ($ ( вместо этого.
  • $ {A: | B} расширяется до элементов массива $ A , которых также нет в массиве $ B .
1
27.01.2020, 20:22

Другое решение, совпадает с началом и концом имен папок:

IFS=$'\n'

folders="""folder1
folder2"""

for folder in *; do
    found=0
    if [ -d "$folder" ]; then
        for i in $folders; do
            if [ $(echo "$folder" | grep -c -E "^$i\$") -eq 1 ]; then
                found=1
            fi
        done
        if [ $found -ne 1 ]; then
            echo "$folder found and deleted."
            rm -rf "$folder"
        fi
    fi
done
3
27.01.2020, 20:22

В системе GNU или FreeBSD вы можете:

cd /target_folder &&
  printf '%s\0' * | grep --null -vxFf names.txt | xargs -r0 rm -rf
0
27.01.2020, 20:22

Теги

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