Как повторить эту команду?

Я быстро протестировал эту процедуру на пустой файловой системе, состоящей из четырех небольших логических томов LVM. Первый вопрос: хотите ли вы оставить его зеркальным (с уменьшенной емкостью )или нет?

Во всем нижеследующем «PATH»— это точка монтирования вашей файловой системы btrfs. Это онлайн-операции.

Если вы не хотите зеркалировать данные (, потому что они не подходят для уменьшенной емкости, например):

  • Избавьтесь от зеркала, преобразовав файловую систему в ту, какой она была бы без него. По умолчанию это дублированные метаданные и одна копия данных. Однако, поскольку у вас все еще есть два диска, метаданные raid1 имеют гораздо больше смысла. Вы делаете это с ребалансом. «Мягкое» здесь означает преобразование только групп блоков -, которые в этом нуждаются — например, метаданные, которые уже являются raid1, не будут затронуты. (То же самое с данными, которые уже являются «одиночными», что может произойти, если вы отмените это на полпути и запустите его снова позже ).

    btrfs balance start -mconvert=raid1,soft -dconvert=single,soft «PATH»
    

    Баланс будет (по умолчанию )работать на переднем плане; вы можете ввести --background, чтобы вернуть терминал (и проверить статус с помощью btrfs balance status «PATH»). Сообщения о состоянии также будут выводиться в dmesg (и, следовательно, в журнал ядра и/или журнал systemd ). Это, вероятно, займет много времени; btrfs любит перемещать данные ☹.

Затем снимите диски . Вы делаете это независимо от того, оставили ли вы его зеркальным или нет.

  • Теперь вы можете удалить два других диска. Это также переместит кучу данных и, следовательно, займет некоторое время. Обратите внимание, что вы можете (и должны )удалить оба диска одновременно, иначе данные могут быть перемещены на диск, который вы хотите удалить следующим.

    btrfs device remove /dev/disk1 /dev/disk2 «PATH»
    

    Обратите внимание, что устройства дисков/разделов располагаются перед точкой монтирования. Опять же, это онлайн-операция. Статус можно посмотреть в журнале ядра.

1
24.01.2021, 22:20
2 ответа

Вы можете использовать цикл for -напрямую с shopt -s globstar:

globstar

If set, the pattern ‘**’ used in a filename expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a ‘/’, only directories and subdirectories match.

shopt -s globstar

d=0;
for file in **/*.mp3; do
  d=$((d + $(mp3info -p "%S" "$file")))
done
mins=$(echo "$d / 60" | bc)
secs=$(echo "$d % 60" | bc)

echo "Total $mins minutes and $secs seconds"
1
18.03.2021, 22:34

Если вы хотите вывести длину отдельной папки, вам понадобится двойной цикл. Первый каталог со списком циклов и второй со списком файлов в каждом каталоге:

#!/bin/bash
OIFS="$IFS"
IFS=$'\n'

function secondToTime () { #Convert second to Day, Hours, Minutes, Seconds
    seconds=$1
    min=0
    hour=0
    day=0
    if((seconds>59));then
        ((sec=seconds%60))
        ((seconds=seconds/60))
        if((seconds>59));then
            ((min=seconds%60))
            ((seconds=seconds/60))
            if((seconds>23));then
                ((hour=seconds%24))
                ((day=seconds/24))
            else
                ((hour=seconds))
            fi
        else
            ((min=seconds))
        fi
    else
        ((sec=seconds))
    fi
    echo "$day"d "$hour"h "$min"m "$sec"s
  }

case $1 in #loop though the first argument
  '-h'|'--help')     # Display the help and exit
    echo "Usage: $0 [PATH]"
    echo "Display the total play time of each folder"
    exit 0
    ;;

  !'')      # Will use the argument as target path
    target=$1
    ;;

  *)        # If no argument is specify it will use the current path
    target='.'
    ;;
esac



for folders in `find $1 -type d ` # Find all sub folders in the specifyed path
do
    for folder in $folders # Loop though each folders
    do
      echo Folder $folder:
    folderTime=0;
        for file in `ls $folder/*.mp3 2> /dev/null` #loop though each files in each folders
        do
            fileTime=`mp3info -p "%S\n" "$file"` #get the time lenght of $file
            isNumber=`echo $fileTime | grep -E '^\-?[0-9]+.?[0-9]*$'` #grep only numbers, if it's not a number isNumber will be empty
            if [ "$isNumber" != '' ]  # Check if $isNumber is NOT empty (which mean that it's a number)
            then
              let "folderTime=$fileTime+$folderTime" #Calculate Total duration in seconds
            fi
        done
        secondToTime $folderTime # Convert seconds to days hours minutes seconds and print it out
    done
done
IFS=$OIFS
0
18.03.2021, 22:34

Теги

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