特定のサイズの下のすべてのディレクトリを移動するには?

特定のサイズの下のすべてのディレクトリを移動するには?

現在のディレクトリから特定のサイズより小さいディレクトリをすべて移動したいと思います。

ここで私は次のように選択しました。

for dir in *
do
    if [[ $(du -s "$dir" | awk '{print $1}') -le 50000 ]]
    then
      ls -l "$dir"
    fi
done

私はdirnameを使ってディレクトリをインポートする必要があると思いますが、どういうわけか私は何をしても文句を言います。 ;)

これを行うための賢い方法はありますか? ;)

答え1

発売作業が正しく行われたと仮定すると、mvコマンドの位置はls -l "$dir"の後と"fi"の前になります。

例: mv $dir /where/you/want/it/re located

ディレクトリ名に""(またはその問題のその他の特殊文字)が含まれていると、問題が発生する可能性があります。これらの問題が発生した場合は、次のように追加の相談を受けることができます。他のスクリプトの内容として使用するために変数をエスケープするスレッドインスピレーション。

答え2

一緒にやるよ

find . -maxdepth 1 -type d | grep -v ^\\.$ | xargs -n 1 du -s | while read size name ; do if [ $size -le 50000 ] ; then mv "$name" /path/to/target/ ; fi done

現在のディレクトリで、サイズが50000未満のすべてのディレクトリを見つけて、ターゲットディレクトリに移動します。

答え3

以下は、1000KB未満の同じレベルにあるすべてのフォルダを移動する例です。

find . -mindepth 1 -maxdepth 1 -type d -exec bash -c 'if [ $(du -d0 {} | cut -f1) -lt 1000 ];then mv {} SOMEWHERE;fi' \;

答え4

GNUシステムで任意のディレクトリ名を処理するには:

du --block-size=1 -l0d1 |
  perl -0 -lne '
    print $2 if /^(\d+)\t(.*)/s && $2 ne "." && $1 < 50000 * 1024' |
  xargs -r0 mv -vt /destination/directory --

duデフォルトのブロックサイズは512ですが、何らかのdu理由でGNUはこれを1024に変更することにしました。ただし、$POSIXLY_CORRECT環境中に変更され、環境変数を介して変更される可能DU_BLOCK_SIZE性があります。BLOCK_SIZEBLOCKSIZE

したがって、コマンドラインで明示的に指定することをお勧めします。ブロックサイズが1の場合、バイト精度でディスク使用量を指定でき、後処理が容易になります²。

-d1同様に、--max-depth=1現在の作業ディレクトリの各サブディレクトリと現在の作業ディレクトリ自体のディスク使用量を取得できます(残念ながらなし--min-depth)。これはdu、すべてのディレクトリで実行されるのを防ぐだけでなく、現在のディレクトリから必要とせずに$2 ne "."削除する必要があるファイルのサイズを計算することを意味しますperldu -- */これは、隠されたディレクトリをスキップせずにディレクトリへのシンボリックリンクが処理されないタスクを実行するよりも利点があります。

これは、これらのディレクトリの再帰降下で見つかったファイルへのすべてのハードリンクを計算する必要があることを意味します-l--count-linksそれ以外の場合、特定のファイルへのハードリンクがサブディレクトリの1つに見つかった場合、そのファイルへの他のハードリンクは計算されません。 。別のディレクトリに接続します。これはまた、与えられたファイルへのハードリンクを意味します。同じサブディレクトリにdu -sまた、すべてが計算されるため、単一のディレクトリで使用するときとは異なる値が表示されることがあります。

duしたがって、ディレクトリツリーにハードリンクが含まれる可能性がある場合は、各ディレクトリに対して1つのハードリンクを呼び出して、互いに独立して計算されることを確認することをお勧めします。

find . ! -name . -prune -type d -printf '%P\0' |
  xargs -r0 -n1 du --block-size=1 -0s -- |
  perl -0 -lne '
    print $2 if /^(\d+)\t(.*)/s && $2 ne "." && $1 < 50000 * 1024' |
  xargs -r0 mv -vt /destination/directory --

同様のポータブルタスクを実行するには(おもちゃボックスdu1を無視する)、次のことができます。

for dir in .* *; do
  [ "$dir" = . ] || [ "$dir" = .. ] && continue
  [ -d "$dir" ] || continue
  [ -L "$dir" ] && continue
  du_output=$(
    LC_ALL=C POSIXLY_CORRECT=1 BLOCK_SIZE=512 BLOCKSIZE=512 DU_BLOCK_SIZE=512 du -s -- "$dir"
  ) || continue # don't take any decision if du fails for that dir
  LC_ALL=C awk -- '
    BEGIN {$0 = ARGV[1]; exit !($1 * 512 < 50000 * 1024)}
    ' "$du_output" || continue

  mv -- "$dir" /destination/directory
done

(検証されていません)。

この方法は、合計4つのコマンドを実行する最初の方法とmv比較して、最大7つのコマンドを実行します。 (ディレクトリの数が多い場合は、より多くのコマンドを複数回実行する必要があります。)ファイルごとこれにより効率がはるかに低下します。


1ビジーボックスやトイボックスなど、主にLinux用に実装された他の実装は、duこの分野の歴史的慣行と標準に従うのではなく、GNUに従うことを選択しました。最悪の場合は、「おもちゃボックス」(Androidで見つかります)で、、、、またはPOSIXLY_CORRECT(バイトBLOCKSIZE)、(キビバイト、デフォルト)、(512)、(メビバイト)オプションはサポートされていません。移植可能な方法(該当する実装を検討する必要がある場合)。BLOCK_SIZEDU_BLOCK_SIZE-b-k-K-mdu

²整数オーバーフローのリスクが増加するが。 512 は通常、最小スペース割り当て単位であるため、ディスクに使用される基本単位として使用することをお勧めします。

関連情報