find -exec lsの出力をソートします


14

find … -exec ls -ls ;ファイル名でアルファベット順にソートして出力することは可能ですか?

これは私のcronコマンドです:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

ほとんどの場合、このコマンドは正常に機能します。ただし、結果は意味のある順序でソートされません。ファイル名フィールドで並べ替える場合、非常に役立ちます。


1
zshを使用していますか?ls -ls **/*(.)
ケビン14

@Kevin完全ではありません— lsソートされます。
ジル「SO-悪であるのをやめる」14

回答:


14

ファイル名に改行が含まれていないことを前提としています。

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

+代わりに;を使用して-execアクションを終了すると、の呼び出しをバッチ処理することでアクションが高速になりますlssortコマンドをパイピングすることでソートできます。10番目のフィールドでソートを開始するように指示します(最初の9つはメタデータです:ブロック、許可、リンク数、ユーザー、グループ、サイズ、3つの日付/時刻フィールド)。このオプション-nls、ユーザーおよびグループに数値を使用するように指示します。これにより、ユーザーまたはグループ名に空白が含まれるリスクを回避できます。

あるいは、zshを使用すると、glob修飾子を使用してファイルを収集およびソートし、コマンドラインが長すぎる場合は複数回zargs実行lsすることで、名前を仮定せずに済ますことができます。再ソートを回避するためにGNU ls(特にその-fオプション)が必要ですls(別のアプローチはlszshでエミュレートすることzstatです)。

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf

どうもありがとうございます!送信した最初のコマンドを使用して並べ替えを行います。より短いパスを使用する場合、数はまだ10ですか?たとえば、public_htmlではなく/ home / setefggeから同じコマンドを実行するとどうなりますか?
MaJ 14

@MaJ 10はスキップされるフィールドの数であり、ファイル名のサイズとは関係ありません。
ジル 'SO-悪であるのをやめる' 14

ありがとうございました。私はあなたの助け、そしてまた他の皆が提供した助けに感謝します。この問題は解決したと思います。私のcronコマンドは現在、ファイルをソートしています。Stackexchangeに質問を送信したのはこれが初めてです。「解決済み」オプションが表示されません。これを解決済みとして投稿する方法を知っている人がいる場合は、先に進んでください。ありがとう!
MaJ 14

@MaJ質問を解決済みとしてマークする最も近い方法は、回答の1つを承認済みとしてマークすることです。質問者であるあなただけがそうすることができます。これを行うには、最も役に立った回答の横にあるチェックマークをクリックします。回答を受け入れると、さらに2レピュテーションポイントを獲得できます。その後、投稿に投票できます。役立つと思われるすべての投稿に投票できます。詳細については、ツアーページヘルプページをご覧ください
ジル 'SO-悪であるのをやめる' 14

1

findの結果を並べ替えてパイプし、各行に対してlsを実行してみませんか?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done

1

POSIXでは、ls -longリストの日付について次のように述べています。

<date and time>フィールドは、ファイルが最後に変更されたときの適切な日付とタイムスタンプを含まなければなりません。POSIXロケールでは、フィールドは次のdateコマンドの出力に相当します。

date "+%b %e %H:%M"

...ファイルが過去6か月間に変更された場合、または:

date "+%b %e %Y"

これを考慮し、ファイル名に改行があるls -q場合、POSIXで指定されたオプションでそれらが適切にグロブされるようにするlsことfindで、結果なしに正規表現をまったく簡単に準備できます。

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

grepそのため、今日または昨日の日付を表す文字列を含む行のみを返します。次のコマンドは、それに少し追加します。

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls オプションの構成:

  1. -a ディレクトリ内のすべてのファイルを返します-で始まるものを含む .dot
  2. -l 長いリスト
  3. -R すべての子ディレクトリを再帰的にリストします
  4. -c アクセス時間ではなく変更時間を表示する
  5. -qファイル名に?印刷不能\t文字またはab文字ではなくシェルグロブを返します

これらの結果は、一致する|pipeファイルsedのみに渡されます。

  1. パス名の前の空白行と次の行
  2. で始まる行- (つまりd、ディレクトリ用ではありません)には、date
  3. ただし、パス名の行は、指定したディレクトリに実際にフィルタしたファイルが含まれていない限り、印刷されません。

出力は次のようになります。

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

はい、それでも動作しますLS_COLORS-これはおそらくあなたにとってはおそらく優先度が低いですcronが、あなたのオプションは開いています。

いずれにせよ、これは他の可能な解決策に比べていくつかの重要な利点を提供します。

  1. そもそもfind+ lsは複数の呼び出しを伴います-これは単一のlsプロセスのみを含み、これがすべてを確実にソートできる理由です-デフォルトで実行されます-そしてsortまた補助的にされます。

  2. findand sortを含むソリューションlsは、ほぼすべての作業を2回実行しています。lsそして、findすべてのパス名とstatすべてのファイルを解決します。lsそしてsort両方のソートすべての結果のでしょう。代わりに、シングルを使用するのがおそらく最善lsです。

  3. それからもちろん、この答えのdateとのsed部分があります。それについて注意することが重要なのは、あなたが難しい部分を行い、最初に正規表現を取得することです-そして一度だけ-そしてその後、あなたは言う、結果を取得する、結果を取得する、結果をソートする、結果をソートするのではなく、結果の単一のリストをプルーニングします。

  4. これは、他のソリューションがそうであるように、改行を含むファイル名では壊れません。このソリューションには独自の注意事項があります(次に説明します)が、細かくて簡単に処理できます。私の意見では、これはここで最も堅牢なソリューションです。

上記のコマンドが問題を引き起こす可能性がある2つのケースがあります。最初は?ファイル名にグロブが含まれます-ここで提供されている他のどのソリューションよりもすでに堅牢なソリューションであり、遭遇?する可能性はそれ自体で十分に小さいですが、それらのグロブを解決する可能性があります複数のファイル名に一致する可能性があります。このテーマの詳細については、こちらをご覧ください。

他の可能性としては、誤検出があります。たとえば、date検索対象の文字列に実際に一致するファイル名grepがあり、そのいずれかの日に実際には変更されていない場合です。私はそれが問題であることを期待していませんが、もしそうなら、それについて尋ねると、おそらくこれを処理するために正規表現をより具体的にするのを助けることができます。


0

実際には、find、xargs、lsの組み合わせを使用できます。

サンプルコマンドを次に示します。 find . -type f -print0 | xargs -0 ls -lt

  • find 現在のディレクトリの下にあるすべてのファイルを再帰的に検索します。
  • xargsは、このファイルのリストをls1回の呼び出しでコマンドに渡します(find返されるのはARG_MAXファイルより少ない場合)。
  • ls -lt これらのファイルを時間でソートし、出力をフォーマットします

システムを取得するには、次のようにARG_MAX入力できます。

$ getconf ARG_MAX
> 2621440

-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)

1
ls独自のソートを行うため、findthrough の出力をパイピングすることsortは無意味です。さらに、コマンドは(特に)空白を含むファイル名をマングルし、ファイル名が多すぎると失敗します。
ジル 'SO-悪であるのをやめる' 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.