すべてのディレクトリで10MB未満のmp4ファイルを繰り返し検索します。

すべてのディレクトリで10MB未満のmp4ファイルを繰り返し検索します。

サイズが10MB未満のmp4ファイルを含むすべてのディレクトリを繰り返し検索しようとしています。

要件は、

  1. ディレクトリにはmp4ファイルが1つしかありません。
  2. mp4ファイルは10MBを超えることはできません。

私が使用するコマンドは

% find . -type f -name "*.mp4" -size -10M | cut -d/ -f2 | sort | uniq -c | grep "^      1"

何が起こっているのかわかりませんが、このコマンドは正確な結果を返しません。

さらなる調査は、次のコマンドが機能することを示しました。

find . -type 'f' -name "*.mp4" -printf '%h\n' | sort | uniq -c | grep -E "\s+1\s"| cut -c 9-

ところでミックスに追加してみると、-size -10000000cそのファイルに10MB未満のmp4ファイルが1つあり、10MBを超える他のmp4ファイルもあることがわかりました。私の言うことは、私が言及したコマンドは、サイズが10MBを超えるmp4ファイルを考慮していないということです。この質問は2段階に分けることができると思います。

  1. mp4ファイルを含むすべてのディレクトリを探します。これは上記のコマンドで行われます。

  2. ファイルが10MB未満であることを確認してください。

次のコマンドを使用して、ディレクトリ内の単一のmp4ファイルのファイルサイズを取得できます。

find . -type 'f' -name "*.mp4" -printf '%h\n' | sort | uniq -c | grep -E "\s+1\s" | cut -c 9-| xargs -I {} -n 1 /usr/bin/du -a "{}" | grep -v ".mp4$"

ベストアンサー1

find少なくともGNUの場合、-size -10Mこれは次のメガバイトに丸められたサイズが10未満(つまり9以下)のファイルの場合に当てはまります。

サイズ9 x 1024 x 1024 + 1 = 9437185バイトのファイルは10MiBに丸められ、10未満ではないため選択されません。

10MB(1MBは1,000,000バイト、1メビバイト== 1,048,576バイトと混同しないでください)より厳しく小さく、サイズが0〜9,999,999のファイルの場合は、以下を使用してください。

find . -size -10000000c

10MiBより厳密に小さいファイルの場合、サイズ範囲は0から10485759です。

find . -size -10485760c

これで、GNUシステムでこれらのファイルの1つだけを含むディレクトリを取得するには、次の手順を実行できます。

LC_ALL=C find . -name '*.mp4'  -type f -size -10000000c -printf '%h\0' |
  LC_ALL=C sort -z |
  LC_ALL=C uniq -zu |
  tr '\0' '\n'

どこ

  • findhこれらのファイルのead(ディレクトリ名)をNULで区切って印刷します(現在のロケールで有効なテキストでなくても、LC_ALL=C他の方法で終わるすべてのファイル名が報告されます)。.mp4
  • sortこれをソートしますuniqLC_ALL=Cファイル名がロケールで有効なテキストではない問題、および文字が完全に定義されている順序ではない問題を回避するためにもう一度)。
  • uniq -zu一意の項目のみが報告されます。

NULはファイルパスには現れない唯一の文字なので、ファイルのリストはNULで区切られて渡されます。私たちはこれらのNULを人が使用できるように改行文字に変換しますtr

を使用すると、zsh次の操作も実行できます。

print -rC1 -- **/*(NFe['()(( $# == 1 )) $REPLY/*.mp4(N.L-10000000Y2)'])

どこ:

  • print -rC1 -- printそれはolumnrの議論です。1 C
  • **/サブディレクトリの数に制限はありません。
  • *(NF...)任意のファイル名(隠しファイルを除く)ですが、、、N... Fglob修飾子でさらにe限定されます。
  • Nnullglob不一致の場合はエラーを返すのではなく、nullに拡張するようにこのglobを有効にします。
  • F:すべてのディレクトリ(Fおよびを除いて1つ以上のエントリを含むディレクトリ)を選択します。...
  • e[code]:成功したファイルを選択してくださいcode
  • () {body} arguments複数のパラメータを持つ匿名関数。
  • 返された算術評価{body}です。(( $# == 1 ))本物この匿名関数のパラメーター数が1の場合。
  • $REPLY内部には、code検討中のファイル(ここではディレクトリ)へのパスがあります。
  • *.mp4(qualifiers): (隠されていない)mp4ファイルはさらに制限されます。
  • .:一般ファイルのみ(例:find's' -type f
  • L-10000000:ファイルサイズは10MBより厳密に小さい。
  • Y2:2つのファイルを見つけて最適化を停止します。

.(現在の作業ディレクトリ自体)は考慮されません。これを考慮したい場合**/*はに変更してください{.,**/*}


ここで明確に説明したように、mp4ファイルが1つしか含まれていないディレクトリを探し、そのファイルが通常のファイル(ディレクトリ、シンボリックリンクではありません...)で、サイズが10 MB未満(たとえばを含むディレクトリを除く):5 MBと15 MB mp4ファイル(サイズに関係なく、複数のmp4があるため、10 MB未満のmp4ファイルが1つしかありませんが)、まだ次のようになりますzsh

print -rC1 -- **/*(NFe['
    () {
      (( $# == 1 )) && ()(($#)) $1(N.L-10000000)
    } $REPLY/*.mp4(NY2)
  '])

GNUfindとGNU awk(またはNULで区切られたレコードを処理できるawk)の場合は、次のようになります。

LC_ALL=C find . -name '*.mp4' -printf '%h\0%s\0%y\0' |
  awk -v RS='\0' '
   {
     getline size; getline type
     total[$0]++
     if (size < 10e6 && type == "f") found[$0]++
   }
   END {for (dir in found) if (total[dir] == 1) print dir}'

おすすめ記事