最新のファイル以外をすべて削除する


8

ḟoo/ある種のディレクトリ構造で多くのファイルを含むディレクトリがあるとします。それらの一部を保持する必要がありますが、すべてを保持する必要はありません。

(たとえば)最新のものを除いてそれらすべてを(その場で)削除する方法はありますか?

回答:


11

私はこのタスクを定期的に行っており、以下のバリエーションを使用しています。これは、さまざまなシンプルなツールを組み合わせたパイプラインです。すべてのファイルを検索し、ファイル変更時間を付加し、並べ替えて、ファイル変更時間を削除し、500以外のすべての行を最初に表示して、それらを削除します。

find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
    sort -r | cut -c14- | tail -n +501 | \
    while read file; do rm -f -- "$file"; done

いくつかのコメント:

  • 「bash」を使用している場合は、「read file」だけでなく、「read -r file」を使用する必要があります。

  • 「perl」を使用してファイルを削除する方が高速です(「read -r file」を使用しない限り、whileループよりもファイル名の「奇妙な」文字をより適切に処理します)。

    ... | tail -n +501 | perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'
    
  • 「tail」の一部のバージョンは「-n」オプションをサポートしていないため、「tail +501」を使用する必要があります。最初の500行をスキップするポータブルな方法は

     ... | perl -wnle 'print if $. > 500' | ...
    
  • ファイル名に改行が含まれている場合は機能しません。

  • GNU findは必要ありません。

上記を組み合わせると、次のようになります。

find foo/ -type f | perl -wple 'printf "%12u ", (stat)[9]' | \
    sort -r | cut -c14- | perl -wnle 'print if $. > 500' | \
    perl -wnle 'unlink() or warn "$_: unlink failed: $!\n"'

私は注意しrm -fます。
CVn

魅力的な作品!これは、$ pathおよび$ countパラメータを持つエイリアスとして使用できる必要があります。どうもありがとう!
DaliborKarlović

4

これは、Python 3でこれを行う方法です。他のOSでも動作するはずです。これをテストした後、ファイルを実際に削除する行のコメントを外してください。

import os,os.path
from collections import defaultdict

FILES_TO_KEEP = 500
ROOT_PATH = r'/tmp/'

tree = defaultdict(list)

# create a dictionary containing file names with their date as the key
for root, dirs, files in os.walk(ROOT_PATH):
    for name in files:
        fname = os.path.join(root,name)
        fdate = os.path.getmtime( fname )
        tree[fdate].append(fname)

# sort this dictionary by date
# locate where the newer files (that you want to keep) end
count = 0
inorder = sorted(tree.keys(),reverse=True)
for key in inorder:
    count += len(tree[key])
    if count >= FILES_TO_KEEP:
        last_key = key
        break

# now you know where the newer files end, older files begin within the dict
# act accordingly
for key in inorder:
    if key < last_key:
        for f in tree[key]:
            print("remove ", f)
            # uncomment this next line to actually remove files
            #os.remove(f)
    else:
        for f in tree[key]:
            print("keep    ", f)

4

「500最新」についてはわかりませんが、Xを使用すると、X分/日より古いものを削除できます。ファイルと2日以上前の例:

find foo/ -mtime +2 -a -type f -exec rm -fv \{\} \;

最初にテストする:

find foo/ -mtime +2 -a -type f -exec ls -al \{\} \;

「\;」の前のバックスラッシュとスペースに注意してください。詳細については、findのマニュアルページを参照してください。


「(最新)500最新」がここでの本質なので、これが元の質問にどのように答えるかはわかりません。
Peter John Acklam、2011年

すみません、よくわかりませんでした。
AndreasM 2011年

3

最新のx番号の代わりにx日/時間古いファイルを保持することができれば、次のようにすることができます tmpwatch --ctime 7d


2

コマンドの-mtimeおよび-newerオプションはfindあなたに役立つと思います。詳しくはこちらman findをご覧ください。


0

なぜこの単純なコードを使わないのですか:

$ ls -t1 foo/| xargs -d '\n' rm --

1
これにより、最新の500ファイルを除くすべてのファイルが削除されますか?そして、これはサブディレクトリをどのように処理しますか?元の投稿を誤解していたと思います。
Peter John Acklam、2011年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.