特定の時間内に変更されたファイルをリストする方法は?


38

22.12.2011から24.12.2011の間に変更されたすべてのファイルを再帰的に一覧表示するにはどうすればよいですか?


6
「最後に変更された」という意味であれば、解決策が見つかる可能性があります。ファイルが2011年12月26日に変更された場合、特定の範囲内でファイルが変更されたかどうかはわかりません。(非常にエキゾチックなファイルシステムがない限り。)
ウィリアムパーセル

回答:


25

一般的に、ディレクトリとそのサブディレクトリ内のファイルを再帰的に検索する場合は、を使用しますfind

日付範囲を指定する最も簡単な方法findは、範囲の境界でファイルを作成し、-newer述語を使用することです。

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop

-newerここで最初の出力を無効にする必要があるのはなぜですか?
アレクサンダーCska

@AlexanderCska最初-newerは否定されず、2番目は否定されます。「より新しいがstart、より新しいファイルを見つけるstop」。
ジル 'SO-悪であるのをやめる'

OK否定は、その後のコマンドで機能します。否定が存在しない場合はどうなりますか?
アレクサンダーCska

@AlexanderCska次に、startとの両方よりも新しいファイルを取得しますstop
ジル 'SO-悪であるのをやめる'

35

Gillesのソリューションを使用して、man find(1)をもう一度読んだ後、より簡単なソリューションを見つけました。最適なオプションは-newerXYです。mおよびtフラグを使用できます。

m   The modification time of the file reference
t   reference is interpreted directly as a time

だから解決策は

find . -type f -newermt 20111222 \! -newermt 20111225

下限は包括的で、上限は排他的であるため、1日を追加しました!そしてそれは再帰的です。find v4.5.9でうまく機能します。


クールなトリック、ありがとう!これは、数千のファイルがあるディレクトリで特定のキーワードを含む最近のファイルを見つけるのに役立ちました:find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l-m 50=最初の50行で検索)。
ロブW

@RobW:実際、次のように-exec ... +in を使用してパイプとxargsを節約できます。これは同じことですが、安価です。find(1)find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +
-TrueY

タイムスタンプを二重引用符で囲む必要がありました(Ubuntu Xenialを使用していますfind 4.7.0-git)。
IsaacS 16

13

すでに与えられた答えに加えて、日付を直接指定できることに注意してください。

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

または

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

さらに時間を指定する場合。


6

秒の精度は必要ないと仮定すると、これは機能するはずです。

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

編集: @Eelvexのコメントの後に変更さcminれましmminた。 編集: '\!' 行方不明


hmは機能していないようです。サブディレクトリを再帰的にたどりますか?
クランプ

はい、動作します。その時間範囲で実際にファイルが変更されていますか?さまざまな時間範囲で試してください。
オヌルgüngör

6
-cmin「ステータス変更」、-mmin「データ変更」です。おそらくしたい-mmin
-Eelvex

3

findISO形式の日付時刻を取ることができるため、たとえばUTCのサーバーの場合、どこにいても時間のオフセットを指定できます。これも時間を比較しているので、1日を追加する必要があります。

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800

0

重複としてマークされた質問は、直接回答することを制限されているため、ここに投稿することに注意してください。この回答は、「作成日に基づいてファイルを別のフォルダに移動する必要がある[重複]」という質問に答えるためのものです。

答えは合理的ですが、純粋にfindコマンドにはいくつかの制限がありました。このシェルスクリプトは、ファイルシステムが非常に多くのファイルを含むディレクトリを通過するように作成し、ファイルシステムがlsを実行しようとしてメタデータを吐き出していました。さらに、一部の* nixシステムでは、lsを実行すると引数が多すぎるというエラーが発生します。

findコマンドは非常に強力であり、リストされている方法から始めましたが、そのディレクトリ全体で長年のデータがあったため、すべてのファイルを繰り返し渡す必要がありました。これにより、各ファイルに不要な多くのパスが渡されます。1年に1つの画面を実行して複数の検索を実行しようとしましたが、これにより各検索から多くのエラーが発生し、検索の1つが移動するとファイルが失われていました。

私のシェルスクリプトは、4桁の年と2桁の月を使用して、ファイルを宛先ディレクトリに移動します。数行のコメントを外し、対応する行をコメントアウトすることで、簡単に2桁の日付に拡張できます。findの1回のパスで移動を実行し、複数のfindコマンドとディレクトリのパスが不要になるため、より効率的だと思います。

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

保存して実行可能にしたら、次のようなfindでこのスクリプトを呼び出すことができます。

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

すべてのfindが提供するファイルごとに単一の実行が提供され、スクリプトがすべての決定を行うため、findのnewermtオプションの設定について心配する必要はありません。

-type fを選択しないと、ディレクトリが移動し、問題が発生する可能性があることに注意してください。ディレクトリだけを移動する場合は、-type dを使用することもできます。タイプを設定しないと、ほぼ確実に望ましくない動作が発生します。

このスクリプトはに合わせて作成されたことを忘れないでくださいニーズ。ニーズのスクリプトにより適したものにするためのインスピレーションとして、単純に私の構成を使用することができます。ありがとうございました!

考慮事項:コマンドの効率は大きくなる可能性があります無制限の数の引数がスクリプトを通過できるようにする改善できます。これは、$ @変数を渡した場合、実際には比較的簡単です。この機能を拡張すると、たとえばfindの-exec +関数を使用したり、xargsを活用したりできます。私はすぐにそれを実装し、自分の答えを改善するかもしれませんが、これは始まりです。

これは1回限りのスクリプトセッションであったため、おそらく多くの改善が可能です。がんばろう!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.