Memo/Linux/find

https://dexlab.net:443/pukiwiki/index.php?Memo/Linux/find
 

find


ファイルが多い/大きい場合の削除

ファイル数が10万等多すぎるとls等の反応が無くなる場合がある。

  • ファイル数が多い場合: 「ls -f」でソート無しならファイルリストは取得できる。
  • ファイルが巨大な場合: truncate --size 0 /path/to/file
# ファイル数の総数
ls -lf /path/to/dir/ | wc -l

# ファイルの先頭100個まで表示
ls -lf /path/to/dir/ | head -n 100

# tmpから始まるファイルを削除
find . -type f -name 'tmp.*' -exec sleep 0.1 \; -print

# 実際に削除: サーバの負荷をかけずに、ゆっくりファイルを消す。秒間10ファイル
nohup nice find . -type f -name 'tmp.*' -exec sleep 0.1 \; -print -delete &

# nohup.out 確認後削除

findの結果をgzファイルにする

gzipは出力ファイル名を指定できない。

  • 「gzip -c example.log > example.foo.gz」は可能だが、元ファイルが残る
  • example.log-YYYYMMDDhhmmss.gz のように任意の名前で圧縮する
    export DATETIME=$(date +%Y%m%d%H%M%S)
    find /var/log/ -type f -name '*.log' \
      -exec mv {} {}-$DATETIME \; \
      -exec gzip {}-$DATETIME \;

findの結果をtar.gzファイルにする

tarの引数としてコマンドラインをそのまま渡すと、ファイルが多い場合に失敗する。そのため標準入力として渡す。

  • 例:/var/log の指定ファイルだけをまとめる
    sudo bash -c "find /var/log/ -type f -mtime -1 -follow \( -name 'messages*' -o -name 'secure*' \) | tar -cvz -T - --null -f logs.$(hostname -s).$(date +%Y%m%d-%H%M%S).tar.gz"
  • /tmp/logsに展開
    mkdir /tmp/logs
    tar xvfz logs.web01.20150616-063248.tar.gz -C /tmp/logs

findで.svnを除外したディレクトリのパーミッションを変更する

  • ディレクトリで、パーミッションが777以外の、.svn, .CVS, .gitを除外し、特定の名前のパーミッションを777に変更する
    find . -type d ! -perm 777 \
    ! \( -path '*.svn*' -prune \) \
    ! \( -path '*.CVS*' -prune \) \
    ! \( -path '*.git*' -prune \) \
    \( -name 'tmp' -or -name 'temp' -or -name 'cache' -or -name 'template_c' -or -name 'log' -or -name 'logs' \) \
    -exec chmod 777 {} \;

findコマンドオプション

  • 最新のファイルを一つ取得
    ls -t $(find /tmp/ -type f -name "*.x86_64.rpm") | head -1
  • ファイル名だけを表示(GNU findのみ)
    find . -type f -printf '%f\n'
  • リンク切れのシンボリックリンクを探す。-followを付けると結果が異なる
    find . -xtype l
  • 古いファイルと空ディレクトリを削除。"/tmp/*" がポイント。"*"が無いと"/tmp/"まで列挙され、削除しようとする
    find /tmp/* -type f -mtime +5 -delete -o -empty -type d -delete
  • 1日以内に変更のあったログを探す
    sudo find /var/log/ -mtime -1 -type f -follow | sort
  • 正規表現。デフォルトではEmacsの正規表現でエスケープが多用される。他に「-regextype posix-egrep」等も指定でき、こちらの方がわかりやすい
    • -typeと併用する場合、-typeより前に書かないと警告が出る
    • -regex pattern パス全体とマッチ。大文字小文字を区別する
      # 拡張子が".log", ".bak", ".tmp", ".old" のファイルを検索
      
      # emacs形式
      find . -regex ".*\.\(log\|bak\|tmp\|old\)$" -type f
      
      # posix-egrep形式
      find . -regextype posix-egrep -regex ".*\.(log|bak|tmp|old)$" -type f
    • -iregex pattern パス全体とマッチ。大文字小文字を区別しない
  • /var/log/ 以下の"*.log"にマッチする 60分以内に変更があったファイルサイズの合計(MB)
    find /var/log/ -name "*.log" -mmin -60 -type f -printf "%s\n" |awk '{sum += $1; printf("\r%d",sum/1024/1024) }; END{print""};'
  • cronで毎日04:05に、/var/log/test 以下の昨日より前の"*.log"ファイルをgz圧縮、90日を経過した"gz"ファイルは削除
    5 5 * * * ( LOG_DIR=/var/log/test; /usr/bin/find $LOG_DIR -follow -name "*.log" -type f -mtime +1 -exec /bin/gzip {} \; ; /usr/bin/find $LOG_DIR -follow -name "*.gz" -type f -mtime +90 -delete; )
  • 削除
    # 空のディレクトリを削除
    find . -empty -type d -delete
    
    # ファイルの削除(-deleteオプションが無いバージョンもあるようだ)
    find . -name '*.log' -delete
    
    # 一つずつファイルを削除
    find . -name '*.log' -exec rm {} \;
    
    # 「+」オプション。xargsのように複数指定
    find . -name '*.log' -exec rm {} +
  • 日付の範囲指定。例:14日前〜7日前までのファイルを列挙
    touch -t `date "+%m%d0000" --date "14 day ago"` /tmp/_start
    touch -t `date "+%m%d0000" --date "7 day ago"` /tmp/_end
    find -newer /tmp/_start -not -newer /tmp/_end
  • -mtime で日、-mmin で分単位で指定できる
    find -mtime -1 1日(24時間)前〜現在 
    find -mtime -3 3日(72時間)前〜現在 
    find -mtime 3  3日(72時間)前〜4日(96時間)前
    find -mtime +3 4日(96時間)前〜過去
    
    # テスト用ファイルを作成
    touch -t `date "+%m%d%H%M" --date "60 min ago"` 60_min_ago.log
    touch -t `date "+%m%d%H%M" --date "1 day ago"` 1_day_ago.log
    touch -t `date "+%m%d%H%M" --date "2 day ago"` 2_day_ago.log
    
    # 70分以前のファイルを検索
    find . -name '*.log' -type f -mmin +70
    ./2_day_ago.log
    ./1_day_ago.log
    
    # 1日以前のファイルを検索
    find . -name '*.log' -type f -mtime +1
    ./2_day_ago.log
  • シンボリックリンク以下も検索したい
    • 例:/var/log/ 以下の*.logファイルを探したいが、/home/user1/log にシンボリックリンクが張ってある場合
      ln -s /home/user1/log /var/log/user1
      
      # 通常 /home/user1/log 以下は表示されない
      find /var/log/ -name "*.log"
      
      # 表示される
      find /var/log/ -follow -name "*.log"
      # または
      find -L /var/log/ -name "*.log"
  • ファイルサイズを指定
    • -size ファイルサイズc
    • k:KB, c:Byte, 指定せず:ブロックサイズ
    • -size 0c :ゼロバイトのファイル
    • -size +1000k :1M B以上のファイル
    • -size -500c :500Byte以下のファイル
      find  /var/log -size +1000k -print
      find  /home -size 0c -print

find+xargs

  • 特定のprefixのサービスを再起動する。例:iptables, ip6tablesを再起動する
    find /etc/rc.d/init.d/ -name 'ip*' -exec basename {} \; | xargs -i sudo /sbin/service {} restart
  • findしてcpやmvしたい場合、xargs -iオプションで"{}"に引数が入る
    find . -name "*.tmp" | xargs -i cp {} /tmp/
  • 日本語ファイル名を含むとエラーになる
    find . -perm 544 | xargs chmod 644
  • find単体では自動的にクォートしてくれるようで動作する
    find . -perm 544 -exec chmod 644 {} \;

空のディレクトリを探す/削除する

  • 空のディレクトリを探す
    find . -type d -empty
  • 空のディレクトリを削除する
    find . -type d -empty -delete

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-10-10 (水) 17:21:20 (13d)