find: 'count=1': 没有这样的文件或目录

find: '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 等...

编辑:

我找到了一种方法,但它看不到隐藏文件,我怎样才能让他们在 for 循环中看到它们?

#!/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

shellcount=$((count+1))在运行之前会展开find

然后find将尝试将参数-exec作为命令执行。这必须是程序或脚本,不能是 shell 内置函数或用于变量赋值的 shell 语法。

无法以这种方式计算找到的文件数,因为find会为 启动一个新进程-exec,因此变量赋值的结果在父 shell 中不可用。

我建议为找到的每个文件打印一行并通过管道输出findto 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

如果设置了 shell 选项,则使用包含 glob 的 globbing 模式**,该模式会匹配 inte 子目录。globstar我还设置dotglob为能够看到隐藏的名称,以及nullglobshell 选项,以便在模式与任何内容都不匹配时完全避免运行循环。

同样的事情,但有一个计数器:

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"

相关内容