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"

相關內容