最も古いファイルをあるディレクトリから別のディレクトリに移動するシェルスクリプト

最も古いファイルをあるディレクトリから別のディレクトリに移動するシェルスクリプト

私はシェルスクリプトに初めて触れました。私は解決策を探しています。ディレクトリにファイルが追加された場合に備えて、私のディレクトリに10個のファイルを保持する必要があります。最も古いファイルだけを別のディレクトリに移動したいと思います。私のディレクトリ名はWorkで、他のディレクトリ名はRegular_archieveと指定しました。私はこれを試しました。

work = /home/balaji/work
regular_archieve = /home/balaji/regular_archieve
cd $work
for i in 'ls -t | sed -e '1,10d' | xargs -d '\n' rm -f'
do
 mv $i $regular_archieve
done
if [ls -t | wc -1 > 10 | mv /home/balaji/regular-archieve]
 then
   echo "more than 10 n files"
fi
mv $(ls -t /home/balaji/work | sed -e '1,10d' | tail - 1) /home/balaji/regular_archieve

ただし、ファイルを別のディレクトリに移動することはできません。

このエラーが発生します。

mv: cannot stat 'file' : No such file or directory

答え1

lsターミナルで見るもの以外の用途での出力を使うのは良いことではありません。バラよりなぜいいえ解析ls(および実行方法)?。代わりに、以下を使用してくださいfind

find /home/balaji/work/ -type f -printf '%C@\t%p\0' |
  sort -z -k1,1 -r -n |
  cut -z -f2 |
  head -z -n 10 | 
  xargs -0r echo mv -t /home/balaji/regular_archive/

findこれには、GNUバージョンの、、、およびsort(または少なくともNULレコード区切り文字オ​​プションをサポートする他のバージョン)cutが必要です。tailxargs-z

  • findすべての一般ファイルに対して-printf '%C@\t%p\0'最後に変更されたタイムスタンプ(%C@1970-01-01 00:00:00以降の秒数)とファイル名()を一覧表示するために使用されます。フィールドは単一のタブ文字()で区切られ、各レコードは%pNUL文字()で\t区切られます。\0
  • findの出力は、-r最初のフィールド()に対してのみファイルを数値逆順()でソートするためにsortにパイプされます。つまり、タイムスタンプに基づいています。-n-k 1,1
  • ソートの出力は、タイムスタンプフィールドを削除するためにパイプに接続されます(ソートが完了した後はもう必要ありません)。
  • カットの出力は、head最初の10項目を得るためにパイプに接続されます。
  • 最後に、head の出力がxargsrunmvコマンドにパイプされます。これはmvのGNU-t拡張子を使用するため、ファイル名の前にターゲットディレクトリを指定できます。

実際、これはrunとecho mvいうよりはrunmvなので、pre-runです。echoそれがあなたが望むことをすることを確信したら、それを取除きなさい。

注:これは以下に適用されます。どの含まれている可能性がある奇妙で迷惑な文字(スペース、改行、シェルメタ文字など)に関係なく、ファイル名。また、このfileコマンドには、検索基準を絞り込むために使用できる他の多くのオプションがあります。


以前のバージョンのGNU coreutils(<バージョン8.25など)を使用している場合cutでも、オプションはありませんhead。代わりにこれを使用できます。例えばtail-zawk

find /home/balaji/work/ -type f -printf '%C@\t%p\0' |
  sort -z -k1,1 -r -n |
  awk -F '\t' 'BEGIN {RS=ORS="\0"}; NR<=10 { $1=""; $0=$0; $1=$1 ; print }' |
  xargs -0r echo mv -t /home/balaji/regular_archive/

perlまたは、次のものを代わりに使用できますawk

 perl -F'\t' -0lane 'if ($. <= 10) {delete $F[0]; print @F}'

答え2

私はあなたのコードで明白な構文エラーを無視し、最近修正された10個のファイルをディレクトリに保存したいと思います~/work。また、zsh利用可能なシェルがあるとします。

次のシェルスクリプトは、zsh最後に変更された10個のファイルを除くすべてのファイルをからに~/work移動します~/regular_archieve

#!/bin/zsh

mv -i $HOME/work/*(.om[11,-1]) $HOME/regular_archieve

スクリプト内の単一のコマンドは、最後に変更された10個のファイルをに保存し、~/work残りのファイルを~/regular_archieve。特定のワイルドカードパターンをmv使用してこれを行いますzsh。パターンは*(.om[11,-1])移動する必要がある通常のファイルに展開されます(ディレクトリが一致しません)。om修正タイムスタンプに基づいてファイルをソートし、このソートされたリスト[11,-1]のファイル名11から最も古いファイルを選択します。出発点グローバル予選 .om[11,-1]globが通常のファイルにのみ一致するようにします。

ディレクトリに何千ものファイルがある場合、「パラメータリストが多すぎます」というエラーが生成されることがあります。この場合、ループを使用してファイルを個別に移動します。

#!/bin/zsh

for pathname in $HOME/work/*(.om[11,-1]); do
    mv -i $pathname $HOME/regular_archieve
done

答え3

この質問に対する別の答えを見つけました。使用するのに最適探す使用する代わりにコマンドエルエス注文する。これにより、最も古いファイルを見つけて使用できるようになります。MV別のディレクトリに移動するコマンドです。

mv $(find /home/balaji/work/ -type f -printf '%T+ %p\n' | sort | head -1) /home/balaji/regular_archieve

find- ディレクトリ階層からファイルを検索します。

/home/balaji/work/– 場所を検索します。

/home/balaji/regular_archieve/- 目標位置。

type -f- 一般ファイルのみを検索します。

-printf ‘%T+ %p\n’- ファイルの最後の変更日時を+記号で区切って印刷します。 (例:2015-07-22+13:42:40.0000000000)。ここで、%pはファイル名を表します。 \n は改行を意味します。

sort | head -n 1- sortコマンドは出力をソートし、出力をheadコマンドに送信して最も古いファイルを表示します。ここで、-n 1 は、最も古いファイルであるファイルが 1 つしかないことを意味します。

関連情報