найти: 'count=1': Такого файла или каталога нет

найти: 'count=1': Такого файла или каталога нет

Предыдущий код:

total=`ls -Rp rootfs | wc -l`
count=0

Когда я присваиваю простое сложение переменной:

sudo find rootfs -exec cp -d -- "{}" "/media/$USER/{}" 2> /dev/null \; -exec sync \; -exec count=$((count+1)) \; -exec echo -en "\rcopiati: $count/$total" \;

Я получил:

find: ‘count=1’: No such file or directory

Также, когда я исполняю:

sudo find rootfs -exec cp -d -- "{}" "/media/$USER/{}" 2> /dev/null \; -exec sync \; -exec count=1 \; -exec echo -en "\rcopiati: $count/$total" \;

У меня та же ошибка. Почему?

Для каждого скопированного файла мне нужен счетчик: 1/13444, который обновляется до 2/13444, 3/13444 и т. д.

редактировать:

Я нашел метод, но он не видит скрытые файлы. Как мне заставить их увидеть их в цикле?

#!/bin/bash
copysync() {
    countfiles() {
        for f in $1/*; do
            if [ -d "$f" ]; then
                countfiles "$f"
            else
                if [ "${f: -2}" != "/*" ]; then
                    total=$((total+1))
                fi
            fi
        done
    }
    recursivecp() {
        for f in $1/*; do
            if [ -d "$f" ]; then
                mkdir -p "/media/$USER/$f"
                recursivecp "$f"
            else
                if [ "${f: -2}" != "/*" ]; then
                    sudo cp -a "$f" "/media/$USER/$f"
                    sudo sync
                    count=$((count+1))
                    echo -en "\rCopied: $((count*100/total))%"
                fi
            fi
        done
    }
    total=0
    countfiles $1
    count=0
    recursivecp $1
}
copysync rootfs

решение1

Оболочка расширяется count=$((count+1))перед запуском find.

Затем findпопытается выполнить аргумент -execкак команду. Это должна быть программа или скрипт, это не может быть встроенная оболочка или синтаксис оболочки для назначения переменных.

Подсчет найденных файлов таким образом не работает, поскольку findзапускает новый процесс для -exec, поэтому результат назначения переменной не будет доступен в родительской оболочке.

Я предлагаю вывести строку для каждого найденного файла и передать вывод в find, wc -lнапример

find rootfs -exec cp -d -- "{}" "/media/$USER/{}" \; -exec sync \; -print|wc -l

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

find rootfs|while IFS= read -r file
do
    cp -d -- "$file" "/media/$USER/$file"
    sync
    count=$((count+1))
    echo -en "\rcopiati: $count/$total"
done

Замечания:

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

Скрипт может не работать, если rootfsсодержит подкаталоги. Вам следует либо обработать этот случай, либо использовать findопции -maxdepthи , -type fчтобы избежать этой проблемы.

решение2

Кажется, вы пытаетесь выполнить каждую команду с помощью -exec. В общем случае это не сработает, так как -execвыполняет только внешние команды.

Вместо этого вызовите один встроенный скрипт и позвольте ему findдействовать как генератор для цикла в этом скрипте:

find rootfs -type f -exec sh -c '
    for pathname do
        cp -d "$pathname" "/media/$USER" &&
        echo . &&
        sync
    done' sh {} + | wc -l

Это найдет все обычные файлы в rootfsкаталоге или ниже. Для пакетов этих файлов sh -cвызывается короткий встроенный скрипт. Этот скрипт копирует каждый файл в указанный каталог, выводит точку, за которой следует новая строка для каждого успешно скопированного файла, и вызывает sync.

Подсчитывает wc -lколичество выведенных точек и сообщает это число. Мы не подсчитываем сами имена путей, поскольку это число может ввести в заблуждение, если какое-либо имя пути содержит встроенный символ новой строки.

Без использования findэто можно сделать, например bash, так:

shopt -s globstar dotglob nullglob

for pathname in rootfs/**/*; do
    [[ ! -f $pathname ]] && continue
    cp -d "$pathname" "/media/$USER" &&
    echo . &&
    sync
done | wc -l

Это использует шаблон подстановки, содержащий **glob, который соответствует подкаталогам inte, если globstarустановлена ​​опция shell. Я также установил dotglobвозможность видеть скрытые имена и nullglobопцию shell, чтобы вообще не запускать цикл, если шаблон ничему не соответствует.

То же самое, но со счетчиком:

shopt -s globstar dotglob nullglob

count=0
for pathname in rootfs/**/*; do
    [[ ! -f $pathname ]] && continue
    cp -d "$pathname" "/media/$USER" &&
    count=$(( count + 1 ))
    sync
done
printf 'count=%d\n' "$count"

Связанный контент