次のスクリプトを実行して、forループを使用してディレクトリ内の各ファイルのサイズを取得しようとします。
#!/bin/bash
FILE=/home/cloudera/Desktop/new
for file in $FILE
do
size=`du -b ${file} | cut -f1`
echo $size
done
次のエラーが発生します。
du cannot access /home/cloudera/Desktop/new/a.txt
du cannot access /home/cloudera/Desktop/new/b.txt
du cannot access /home/cloudera/Desktop/new/c.txt
そのうち、a.txtとb.txt.c.txtは新しいディレクトリにあるファイルです。
答え1
du -b
代わりに find と printf を使用することをお勧めします。ここで最大の問題は、duが見つけたすべてのディレクトリに再帰することです。ループfor
では個々のファイルを見ることはできません。
find /home/cloudera/Desktop/new -type f -printf "%s %p\n"
見つかった項目に printf がない場合は、次のようにします。
-exec stat -c "%s %n" {} \;
次に、出力をwhileスクリプトにパイプします。
find <what you do above> |
while read size ; do
# whatever
done
編集:SOURCEDIRで各ファイルを見つけて、DESTDIRにファイルが存在しないか存在するがサイズが異なる場合は、ファイルをコピーしたいようです。
CP="echo /bin/cp -f"
sizeof() { stat -c %s "%1" ; }
cd $SOURCEDIR
find . -type f -print |
while read name; do
source_size=$(sizeof $SOURCEDIR/$name)
if [[ -f $DESTDIR/$name ]]; then
dest_size=$(sizeof $DESTDIR/$name)
if [[ $source_size == $dest_size ]]; then
next # do not copy
fi
fi
$CP $SOURCEDIR/$name $DESTDIR/$name
done
しかし、これは醜く遅いです。cd
findの出力がすべて相対パスであることを確認する必要があります。以降の使用は明確にする$SOURCEDIR
ために重複します。別の名前sizeof
に変更できるようにエイリアスを指定しましたdu -b
。出力が正しい場合は、$CP
実際のコマンド(remove echo
)に変更してください。
これを行う別の方法があります。勉強がうまくいけば、UNIXについてたくさん学ぶことになります。
CP="echo cp"
{ cd $SOURCEDIR ; find . -type f -printf "%s %p\n" |sort -k 2 ; } >/tmp/source.lst
{ cd $DESTDIR ; find . -type f -printf "%s %p\n" |sort -k 2 ; } >/tmp/dest.lst
awk 'FNR==NR { f[$2]=$1 } !length(f[$2]) || f[$2]!=$1 { print $2 }' /tmp/dest.lst /tmp/source.lst >/tmp/copythese.lst
cat /tmp/copythese.lst | xargs -n 1 -I ^ $CP $SOURCEDIR/^ $DESTDIR/^
テストを見てください。その後、リストが正しいと思われる場合は、前のコマンドCP
に変更して繰り返します。/bin/cp -f
上記の手順を実行しますが、リストを使用しています。 awk コマンドは、ターゲットに存在しないファイルまたはサイズの異なるファイルをソースから検索します。 ($1 はサイズ、$2 はファイル名、$f[$2] はファイルサイズ目的地)。次に、各行に対してxargs
1つのインスタンスを実行します。$CP
copythese.lst
答え2
#!/bin/bash
DIR=/home/cloudera/Desktop/new
for file in $DIR/*
do
wc -c "$file"
done
答え3
スクリプトは、ファイルまたはディレクトリである可能性がある独自のサイズ(バイト)のペアを<SIZE> <FILE>
表示します。ファイルのみを表示するには、最初の条件を削除して2番目の条件を使用する必要があります。<SIZE>
<FILE>
#!/bin/bash
FILE=/home/cloudera/Desktop/new
for i in `ls $FILE`
do
if [ -d "$FILE/$i" ]
then
msg=`ls -ld $FILE/$i`
size=$(echo $msg | awk -F [\ ] '{print $5}')
file=$(echo $msg | awk -F [\ ] '{print $9}')
echo -e "$size \t $file"
elif [ -f "$FILE/$i" ]
then
msg=`ls -l $FILE/$i`
size=$(echo $msg | awk -F [\ ] '{print $5}')
file=$(echo $msg | awk -F [\ ] '{print $9}')
echo -e "$size \t $file"
fi
done