Оператор If, указывающий, находится ли файл в каталоге [дубликат]

Если вы хотите хранить образы дисков KVM/QEMU в неиспользуемых разделах, у вас есть несколько вариантов:

В любом случае вам понадобится создать новый пул хранения; что вы можете сделать с помощью virt-manager. Но варианты выше работают по-разному.

Подход на основе разделов на самом деле является вводящим в заблуждение названием. Вы могли бы подумать, что он использует раздел для каждого образа диска, но на самом деле он форматирует раздел с файловой системой по вашему выбору, монтирует его и сохраняет образы дисков в файловой системе. По функциональности он ничем не отличается от тома хранилища по умолчанию /var/lib/libvirt/images/.

Пул хранения на основе LVM использует другой подход. Он создает логический том для каждого образа диска. Таким образом, существует сопоставление 1:1 между образом диска VM и томом LVM.

Если у вас есть пул хранения, вы можете использовать его при создании новых виртуальных машин. Что касается перемещения существующих образов, то это прямолинейно с подходом «на основе разделов»: скопируйте образы, а затем измените виртуальную машину, чтобы она указывала на скопированный образ. Для LVM... Честно говоря, я не уверен. Простой ddдля логического тома может сработать.

1
17.11.2018, 03:21
3 ответа

Вот рабочая версия с использованием вашего подхода:

#!/bin/bash
fileList="$1"
targetDir="$2"

## Read the list of files into an associative array
declare -A filesInFile
while IFS= read -r file; do
  filesInFile["$file"]=1
done < "$fileList"

## Collect the files in the target dir
filesInDir=("$targetDir"/*);

for file in "${filesInDir[@]}"; do
  file=${file##*/}; # get the name of the file; remove path
  ## If this file has no entry in the array, delete
  if [[ -z "${filesInFile[$file]}" ]]; then
      echo "rm $file"
  fi
done

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

2
27.01.2020, 23:12

Сzsh:

expected=(${(f)"$(<fileNames.txt)"}) || exit
cd TestDir || exit
actual=(*(D))
superfluous=(${actual:|expected})
if (($#superfluous)) {
  echo These files are not in the expected list:
  printf ' - %q\n' $superfluous
  read -q '?Do you want to delete them? ' && rm -rf -- $superfluous
}
2
27.01.2020, 23:12

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

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.

3
27.01.2020, 23:12

Теги

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