
前のコード:
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
シェルはcount=$((count+1))
実行前に拡張されますfind
。
次に、引数をコマンドとして実行find
しようとします。-exec
これは、シェル組み込み関数や変数を割り当てるシェル構文ではなく、プログラムまたはスクリプトでなければなりません。
find
新しいプロセスが開始されるため、見つかったファイルの数はこの方法でカウントできないため、変数の割り当て-exec
結果は親シェルで使用できません。
見つかったファイルごとに1行印刷して出力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
シェルオプションが設定されている場合、**
inte サブディレクトリに一致する glob を含む globbing パターンが使用されます。また、パターンが一致しない場合は、実行ループを完全に避けるために隠された名前とシェルオプションを表示するようにglobstar
設定しました。dotglob
nullglob
同じことですが、カウンターがある場合:
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"