ディレクトリ内のフォルダから最も古いファイルを選択する方法[重複]

ディレクトリ内のフォルダから最も古いファイルを選択する方法[重複]

私のディレクトリにはnたくさんのファイルがあります../in/。これらのファイルの中で最も古いファイルを処理してその../complete/ディレクトリに送信したいと思います。残りのファイルはこの../error/ディレクトリに転送されます。誰でも助けることができますか?

答え1

最も古いファイルをコピーするには../complete:

cp -v "$(find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '1s/[0-9,\.]\+ //p')" ../complete

最も古いものを除くすべてをコピーするには、次の手順を実行します../error

find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '2,$s/[0-9,\.]\+ //p' | xargs -0 cp -vt ../error

説明する:

  • find
    • -maxdepth 11つのレベルだけが下がるので、ディレクトリを繰り返し検索しません。
    • -type fファイルのみが一致します。
    • -printf '...'カスタム出力形式。%T@ファイルの最後の変更時刻(タイムスタンプ)を提供し、%pファイル名。\0最後まで注意してください。ファイルは改行ではなくヌルバイトで区切られて印刷されます。これは、改行がファイル名の文字である可能性があるため、コマンドが中断される可能性があるためです。
  • sort -znその後、ヌルバイトで区切られた出力を読み取り()、-z数字でソートします(-n)。
  • sed -znヌルバイトで区切られた出力を読み取ります。
    • 1最初の行(最初のコマンド)のみが一致し、2,$他のすべての行(2番目のコマンド)と一致します。
    • s/[0-9,\.]\+ //p先行タイムスタンプが出力から削除されます。
  • 2番目のコマンドのみ:xargs -0 cp -vt ../errorヌルバイトで区切られた()出力を処理し、-0ファイルcp -vt ../errorをコピーするすべての入力を呼び出します。

出力例:

$ ls -lt ../in/
total 0
-rw-r--r-- 1 user user 0 Jun 24 08:18 file2
-rw-r--r-- 1 user user 0 Jun 24 08:18 file3
-rw-r--r-- 1 user user 0 Jun 24 08:18 file4
-rw-r--r-- 1 user user 0 Jun 24 08:18 file5
-rw-r--r-- 1 user user 0 Jun 24 08:17 file_oldest
$ cp -v "$(...)" ../complete
'../in/file_oldest' -> '../complete/file_oldest'
$
$ find ... | xargs ... ../error
'../in/file2' -> '../error/file2'
'../in/file3' -> '../error/file3'
'../in/file4' -> '../error/file4'
'../in/file5' -> '../error/file5'

答え2

最も古いファイルを見つけて目的のディレクトリに移動するには、次のようにします。

# cd to ../in/

$ ls -lt | grep -v '^d' | tail -1 | awk '{print $NF}' | xargs -I '{}' mv '{}' ../complete/

これで、最も古いファイルが移動されたので、すべてのファイルを次の場所に移動できます。../error/

$ mv -- * ../error/

について質問がある場合--mv-

答え3

確立されたラフルの答え:

$ ls -ltr | grep -v '^d' | awk 'NR==2 {print $NF; exit}' | xargs -I '{}' mv -- '{}' ../complete/

メモ:

  • 「最も古いファイル」で何かをしたいと言われました。すべての回答は、最後に変更された内容を意味すると仮定します。一番最近の馬なら変更、そう言うと答えは少し違うでしょう。最近話すなら作られた、あなたが望むのはUnixではほとんど不可能です。
  • ls -lt(Rahulで使用)現在のディレクトリを変更された日付/時刻の順序、最新の項目、最も古い項目の順に長い形式で一覧表示します。  ls -ltr~であるアル字型対照的に、最も古いものは最初にソートされ、最新のものは最後にソートされます。
  • ピリオド(.)、例えば。Aにオプションを追加します。 (オプションの順序は重要ではありません。必要に応じて、またはを使用できます。)lsls -ltrAls -ltArls -lAtrls -ltr -A
  • 私は嘘をついた。ls長いディレクトリのリストは常にtotal1行で始まります。の中でls -ltr最も古い項目が にあります。第二ワイヤー。
  • grep -v '^d'ディレクトリがある場合はフィルタリングします。
  • awk 'NR==2 { print $NF; exit }' 2行目(最も古いファイル)の最後のフィールド(filename *)を印刷して終了します。

    • プロセスが1つ減りますtail -1 | awk '{print $NF}'
    • awkシャットダウン時にlsシャットダウンすることも、完全なディレクトリリストを作成する必要もないため、この方法はより速く機能します。
    • grep以下を実行して削除できます。

      ls -ltr | awk '! /^d/ { count++ } count==2 { print $NF; exit }'
      

      しかし、私はこれをお勧めしません。複雑すぎるスクリプトはメンテナンスが困難です。

  • --以来mv xargs指揮中これは、ファイル名が次から始まる場合に必要です。-
  • 実際にはそうする必要はありませんxargs。上記のコマンドは次のように単純化できます。

    $ mv -- $(ls -ltr | grep -v '^d' | awk 'NR==2 { print $NF; exit }') ../complete/
    

________
* Rahulの答えと同様に、ファイル名にスペースやタブが含まれていると失敗します。ファイル名に改行文字が含まれていると、さらに悪化します。

ピリオド(.)、shopt -s dotglob前に最初にしてください

$ mv -- * ../error/

関連情報