変更日で再帰的にソートされたファイルをリストする方法(statコマンドは利用できません!)


31

現在のディレクトリの下にあるすべてのファイルのリストを、変更日とその日付で並べ替えるにはどうすればよいですか?

今、私はfindstatおよびsortでそれを達成する方法を知っていますが、何らかの奇妙な理由でstatがボックスにインストールされておらず、インストールできる可能性は低いです。

他のオプションはありますか?

PS:gccどちらもインストールされていません


コンパイル済みのバイナリをアップロードして実行できますか?
imz-イヴァンザカリヤシェフ

@imz:はい、それは別の方法です。しかし、find -printfアクションは最も簡単なようです。
アレックス

回答:


27

私の最短の方法はzshを使用しています:

print -rl -- **/*(.Om)

D隠しファイルまたは隠しディレクトリ内のファイルも一覧表示する場合は、glob修飾子を追加します)。

GNU findがある場合は、ファイルの変更時刻を出力し、それでソートします。ファイル名に改行がないと思います。

find . -type f -printf '%T@ %p\n' | sort -k 1 -n | sed 's/^[^ ]* //'

Perlを使用している場合(再び、ファイル名に改行がないと仮定):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

Pythonを使用している場合(ファイル名に改行がないと仮定します):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'

そのサーバーへのSSHアクセスがある場合は、設備の整ったマシンでsshfsを介してディレクトリをマウントします。

mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt

POSIXツールだけでは、ファイルの変更時間を見つける良い方法がないため、はるかに複雑です。ファイルの時間を取得する唯一の標準的な方法はlsであり、出力形式はロケールに依存しており、解析が困難です。

ファイルに書き込むことができ、通常のファイルのみに関心があり、ファイル名に改行がない場合、恐ろしいことです:単一のディレクトリ内のすべてのファイルへのハードリンクを作成し、変更時間で並べ替えます。

set -ef                       # disable globbing
IFS='
'                             # split $(foo) only at newlines
set -- $(find . -type f)      # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do                     # hard link the files to links.tmp/0, links.tmp/1, …
  ln "../$f" $i
  i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do  # for each file, in reverse mtime order:
  eval 'list="${'$i'}         # prepend the file name to $list
$list"'
done
printf %s "$list"             # print the output
rm -f [0-9]*                  # clean up
cd ..
rmdir links.tmp

最も簡単な方法はおそらくfind . -print | xargs -n99999 -s999999 ls -ltrです。ただし、(1)512を超えることも5120を超えるxargsことも許可されない可能性があり、(b)回避できたとしても、結合された引数リストと環境の最大サイズがカーネルによって課されるという問題があります。ほとんどのアイデア(PerlとPythonのアイデアを保存する)には同じ問題があります。そのため、長いコマンドラインの作成を特に避けました。-m-s
ギーコサウルス

特に、zsh一般的な場合に再帰的なグロブを使用すると、「引数リストが長すぎます」というエラーが定期的に発生します。
ギーコサウルス

@geekosaur:最後の恐ろしいクラッジだけが長いコマンドラインで問題を抱えています。zshでは、ビルトインで多くのことができます(たとえば、print -rl **/*唯一の制限は使用可能な空きメモリの量です)zargs。の提案が1回だけ呼び出されたfind … | xargs … ls場合、正しく提案され、ファイル名に特殊文字が含まれていると機能しません。xargsls
ジル 'SO-悪である停止

非常に詳細な回答と多くのオプションに感謝します!:)
アレックス

それが私がzshが好きな理由です。
Profpatsch

14

GNUを想定find

find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-

ファイルを最新のものから順に表示したい場合に変更1n,11nr,1ます。

GNUを持っていない場合、タイムスタンプの形式が非常に異なるため(たとえば、最近変更されたファイルのタイムスタンプのスタイルが異なります)、findより困難になりlsます。


実際には、日付と時刻の形式を変更することもできますls --time-style="..."-これが標準かGNU ls、おそらくGNUかはわかりません。
asoundmove

間違いなくGNU。
ギーコサウルス

@asoundmove:残念ながら、ボックスは古すぎ(RedHat 7.2)、lsそのオプションはありません。
アレックス

7

Macでは、見つけるための-printf引数はありませんが、代わりにこれを行うことができます。

find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'



0

隠しファイルを無視—素晴らしく高速なタイムスタンプ付き

ファイル名のスペースを適切に処理します。使用する必要はありません。

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht

findリンクをたどると、さらに多くの情報が見つかります。


0

一般に日付によるファイルの検索について言えば(これは元のポスターでは機能しませんが、私はここにたどり着いたので、他の人も同様だと思いました)。私のユースケースでは、削除する前にファイルを確認する目的でファイルをリストします。

findutils 4.6.0では、次のことが好きです。

find . -type f -mtime +270 -exec ls -laFGht --time-style=iso {} \+

上記のコマンドは-type f、現在の作業ディレクトリ(.)で、270日以上前に変更されたファイル()を検索します(-mtime +270また-mtime 0、過去24時間を生成し-mtime -5、過去5日間を表示します)。次にls、日付順にリストし、最新のものから順に表示します(-exec ls -laFGht --time-style=iso {} \+

出力のサンプルは次のとおりです。

-rwxrwx---+ 1 user1 208M 2018-07-16  ./filename.bak*
-rwxrwx---+ 1 user1  702 2018-07-15  ./filename.ldf*
-rwxrwx---+ 1 user1 208M 2018-07-15  ./filename.bak*

これの素晴らしい点は、リストを確認したら、リスト部分をfind削除コマンドに置き換える簡単なことです:

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