私のディレクトリには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 1
1つのレベルだけが下がるので、ディレクトリを繰り返し検索しません。-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
にオプションを追加します。 (オプションの順序は重要ではありません。必要に応じて、またはを使用できます。)ls
ls -ltrA
ls -ltAr
ls -lAtr
ls -ltr -A
- 私は嘘をついた。
ls
長いディレクトリのリストは常にtotal
1行で始まります。の中で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 }'
しかし、私はこれをお勧めしません。複雑すぎるスクリプトはメンテナンスが困難です。
- プロセスが1つ減ります
--
以来mv
xargs
指揮中これは、ファイル名が次から始まる場合に必要です。-
。実際にはそうする必要はありません
xargs
。上記のコマンドは次のように単純化できます。$ mv -- $(ls -ltr | grep -v '^d' | awk 'NR==2 { print $NF; exit }') ../complete/
________
* Rahulの答えと同様に、ファイル名にスペースやタブが含まれていると失敗します。ファイル名に改行文字が含まれていると、さらに悪化します。
ピリオド(.
)、shopt -s dotglob
前に最初にしてください
$ mv -- * ../error/