質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Tera Term

Tera Termは、TeraTerm Projectが開発する国産のWindows向けターミナルソフト。telnetプロトコルでのリモートホストへの接続やCOMポートのシリアル接続が可能で、マクロが利用できます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

Q&A

4回答

595閲覧

Linux上でファイルのタイムスタンプによる検索条件の指定

K_Emi1224

総合スコア1

Tera Term

Tera Termは、TeraTerm Projectが開発する国産のWindows向けターミナルソフト。telnetプロトコルでのリモートホストへの接続やCOMポートのシリアル接続が可能で、マクロが利用できます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

1グッド

0クリップ

投稿2023/11/19 14:43

ご質問させていただきます。

Linux上である1つのディレクトリ配下にあるファイル1つ1つの行数をカウントし、さらにそれの月ごとの合計値を出したいです。
例として、あるディレクトリ配下が下記であった時、
11月 9 20:00 a.txt
11月 10 20:30 b.txt
11月 27 21:00 c.txt

3つのa.txt、b.txt、c.txtの行数がそれぞれ1,2,3であれば、6と出力するコマンドを作成しようとしています。
ここで問題なのが、ファイル名にYYYYMMDDのような日付形式の情報が一切含まれておらず、タイムスタンプからしかそのファイルの日付情報を読み取れないことです。

このような場合に上記のようなことは可能なのでしょうか。
一つのファイルの行数を取得するのはwc -l ファイル名で簡単に取得できますから、月ごとの・・・という条件指定でパイプで繋げば可能かと思っているのですが、自分なりにタイムスタンプ、、集計、、といったワードで調べてみてもいまいち該当の情報にヒットしません。

正直なところ、八方塞がり状態でして、有識者の方々お知恵を貸していただけないでしょうか。
よろしくお願いいたします。

arcxor👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

arcxor

2023/11/19 14:53

ファイルシステムのタイムスタンプには atime, ctime, mtime がありますが、mtime を使って集計したいということでしょうか。
ikedas

2023/11/19 23:29

使っているLinuxのディストリビューション名とバージョンを明記してください (質問文を編集して追記してください)。ディストリビューションによってlsなどの仕様が異なることがあります。
guest

回答4

0

私ならperlを使います。

  • OSごとのコマンドの仕様の違いなどをほぼ気にせずに済む。
  • 機能拡張も容易でつぶしが効く。

そして今ならChatGPTという強い味方が使えます。次のようなプロンプトを投入してみました。

イメージ説明

これにより次のようなスクリプトが得られました。

#!/usr/local/bin/perl use strict; use warnings; use CGI; use Encode; my $q = CGI->new; print $q->header(-type => 'text/html', -charset => 'UTF-8'); my $name = $q->param('Name') // ''; # Initialize $name to an empty string if it's not defined $name = encode('utf-8', $name) if $name; print <<EOM; <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>テストのCGIページ</title> </head> <body> <input type="text" value="$name"> </body> </html> EOM

私の環境で試したところでは、ほぼ修正なしで目的を達成できました。私は有料ChatGPTユーザーなのでこのような選択をしましたが、Google bardやBing Chatでも行けるのではないかと思います。

投稿2023/11/20 05:31

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

init.sh

bash

1#!/bin/bash 2 3mkdir -p testdir/dir 4 5for i in $(seq 1 9); do 6 for k in $(seq 1 $i); do 7 echo $k >> testdir/${i}.txt 8 done 9done 10 11touch -t 202201010000 testdir/1.txt 12touch -t 202201020000 testdir/2.txt 13touch -t 202301030000 testdir/3.txt 14touch -t 202301040000 testdir/4.txt 15touch -t 202301050000 testdir/5.txt 16touch -t 202302060000 testdir/6.txt 17touch -t 202302070000 testdir/7.txt 18touch -t 202303080000 testdir/8.txt 19touch -t 202304090000 testdir/9.txt 20 21for i in $(seq 5 9); do 22 mv testdir/${i}.txt testdir/dir 23done

main.sh

bash

1#!/bin/bash 2 3lines=$(join -j2 -o '1.1 1.2 2.1' <(find . -type f -printf '%TY-%Tm %p\n' | sort -k2) <(find . -type f | xargs wc -l | sort -k2) | sort -V) 4lines=$(echo "$lines" | awk '{ map[$1] = map[$1] "\t" $3 " " $2 } END { for(key in map) print key map[key] }' | sort -V) 5 6IFS=$'\n' 7for line in $(echo "$lines"); do 8 strs=$(echo "$line" | tr $'\t' $'\n') 9 time=$(echo "$strs" | head -n 1) 10 strs=$(echo "$strs" | tail -n +2) 11 sum=$(echo "$strs" | awk '{s += $1} END {print s}') 12 echo "==== $time: $sum" 13 echo "$strs" 14 echo 15done

output

sh

1cd testdir 2../main.sh

text

1==== 2022-01: 3 21 ./1.txt 32 ./2.txt 4 5==== 2023-01: 12 63 ./3.txt 74 ./4.txt 85 ./dir/5.txt 9 10==== 2023-02: 13 116 ./dir/6.txt 127 ./dir/7.txt 13 14==== 2023-03: 8 158 ./dir/8.txt 16 17==== 2023-04: 9 189 ./dir/9.txt

投稿2023/11/19 17:30

編集2023/11/21 10:30
arcxor

総合スコア2859

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

find-daystart -mtime等を使ってある月の範囲のファイルだけに対してコマンドを実行するのは可能ですが、日付の指定が「今から何日前」という指定になるので、「2023年8月のファイル」という指定が面倒です。日付の計算をすれば良いだけなので、面倒と言うだけで難しいわけじゃ無いですが。
-newerを使う方法も考えられるが説明が面倒なので略)

簡明にやるには、

一つのファイルの行数を取得するのはwc -l ファイル名で簡単に取得できますから、月ごとの・・・という条件指定でパイプで繋げば可能かと思っているのですが、自分なりにタイムスタンプ、、集計、、といったワードで調べてみてもいまいち該当の情報にヒットしません。

と言う方針を捨てるのが良いです。
すべてのファイルについて、年月と行数を求めて2023-08 1234のような出力をして、それをawk等で集計すれば良いでしょう。

sh

1for file in *.txt 2do echo $(date +%Y-%m -r "$file") $(wc -l <"$file") 3done | 4awk '{A[$1]+=$2}END{for(i in A) print i,A[i]}' | 5sort

dateコマンドで使われるタイムゾーンで月の区切りを決めるので希望と違えば適切にタイムゾーンを設定します。

投稿2023/11/19 16:07

otn

総合スコア84633

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

bash

1$ stat -c "%y %n" *.txt 22023-11-09 20:00:00.000000000 +0900 1.txt 32023-12-02 21:00:00.000000000 +0900 2.txt 42023-11-10 20:30:00.000000000 +0900 3.txt 52023-12-10 21:00:00.000000000 +0900 4.txt 62023-02-20 21:00:00.000000000 +0900 5.txt 72023-01-10 21:00:00.000000000 +0900 6.txt 82023-11-27 21:00:00.000000000 +0900 7.txt 92023-02-10 21:00:00.000000000 +0900 8.txt 102023-01-20 21:00:00.000000000 +0900 9.txt 11 12$ find . -maxdepth 1 -type f -printf '%TY-%Tm ' -exec wc -l {} \; | 13awk '{ cnt[$1] += $2 }END{ 14 PROCINFO["sorted_in"] = "@ind_str_asc" 15 for(i in cnt) printf("%s:%4d\n", i, cnt[i]) 16}' 17 182023-01: 14 192023-02: 24 202023-11: 6 212023-12: 17

投稿2023/11/19 16:00

編集2023/11/20 16:21
melian

総合スコア19825

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問