96853


## やりたいこと

ディレクトリ内の全てのファイルを対象に、`ls -l` の結果の一部と、`wc -l` の結果の一部をマージした結果を得たいと考えています。

具体的には次のような結果です。1列目にファイルの mtime の年月日、2列目にファイルパス、3列目に行数があるような結果です。

### 得たい結果

[code]

    2020-02-06 ./index.php 17
    2023-01-01 ./license.txt 384
    2023-07-06 ./readme.html 97
    2023-05-13 ./wp-activate.php 218
    2023-11-09 ./wp-admin/about.php 381
    ...
    
[/code]

なお、上記はサンプルファイルとして [wordpress.zip](https://wordpress.org/latest.zip) で試した結果です。

この結果は、次のような for 文を書けば得られるのですが、for
文を使っているためか1行ずつの処理になってしまい、ファイル数が多いと結果を得られるのが遅くなってしまっています。wordpress
のファイル群で試すと手元で10秒ほどかかってしまっています。

[code]

    IFS=$'\n'
    for line in $(find . -type f | sort | xargs ls -l --time-style='+%Y-%m-%d' | awk '{print $6, $7}'); do
        file=$(echo "$line" | awk '{print $2}')
        echo "$line" $(cat "$file" | wc -l)
    done
    
[/code]

### 高速に実行できる方法

一方で、次のコマンドは高速に全ファイルの結果を得ることができます。

[code]

    find . -type f | sort | xargs ls -l --time-style='+%Y-%m-%d' | awk '{print $6, $7}' 
    
[/code]

[code]

    2020-02-06 ./index.php
    2023-01-01 ./license.txt
    2023-07-06 ./readme.html
    2023-05-13 ./wp-activate.php
    2023-11-09 ./wp-admin/about.php
    ...
    
[/code]

[code]

    find . -type f | sort | xargs wc -l  
    
[/code]

[code]

          17 ./index.php
         384 ./license.txt
          97 ./readme.html
         218 ./wp-activate.php
         381 ./wp-admin/about.php
    ...
    
[/code]

この `ls -l` と `wc -l`
の結果をマージしたような、冒頭に示した「得たい結果」を高速に得たいのですが、どのような方法が考えられるでしょうか。2つのコマンドの結果をマージするような方法があるのか、または「得たい結果」を高速に得るコマンドがあるのかについてお尋ねしたいです。

## 補足

GNU bash 5.x を使っています。（もし例えば zsh なら簡単にできるなどあれば教えていただけると助かります）


CC BY-SA 4.0
2023-11-20T11:53:11.397
96852
2023-11-21T12:00:35.823
51937
question
bash shell
高速に ls -l と wc -l の結果をマージした出力結果を得たい


パスにスペース含まないなら, こんな風にできます  
~~(sort 組み込んでいないので適当なところへ。joinしてるので片方だけでも OKなはず)~~

[code]

    join -j2 <(find -type f -printf "%TF %p\n") <(find -type f -exec wc -l {} +) |awk '{print $2 " " $1 " "$3}'
    
    # 結果サンプル
    2022-11-22 ./HackGen_v2.7.1.zip 153552
    2023-07-13 ./wezterm-20230712-072601-f4abf8fd.Ubuntu22.04.deb 153955
    
[/code]

* * *

**update**  
(join用に)ソートする場合  
(ファイル数が増えても大丈夫のはず)

[code]

    $ join -j2 -o '1.1 1.2 2.1' <(find . -type f -printf '%TF %p\n' |sort -k2,2) <(find . -type f -exec wc -l {} + |sort -k2,2)
    
[/code]


CC BY-SA 4.0
2023-11-20T13:31:19.947
96853
2023-11-21T12:00:35.823
2023-11-21T12:00:35.823
43025
43025
96852
answer

[code]

    $ stat --version
    stat (GNU coreutils) 9.1
    
    $ paste <(find . -type f -exec stat -c '%y %n' {} \+ | cut -d' ' -f1,4-) \
            <(find . -type f -exec wc -l {} \+ | grep '/') | \
      sort -k2,2 | awk '{NF-=1}1'
    
    2020-02-06 ./index.php 17
    2023-01-01 ./license.txt 384
    2023-07-06 ./readme.html 97
    2023-05-13 ./wp-activate.php 218
              :
    
    # 実行時間
    $ time { paste <(find . -type f -exec stat -c '%y %n' {} \+ | cut -d' ' -f1,4-) \
                   <(find . -type f -exec wc -l {} \+ | grep '/') | \
             sort -k2,2 | awk '{NF-=1}1'; }
          :
    
    real  0m0.082s
    user  0m0.022s
     sys  0m0.012s
    
    # 実行時間(質問文に掲示されているコード)
    $ time { IFS=$'\n';for line in $(find . -type f | sort | xargs ls -l --time-style='+%Y-%m-%d' | awk '{print $6, $7}'); do
        file=$(echo "$line" | awk '{print $2}')
        echo "$line" $(cat "$file" | wc -l)
    done; }
              :
    
    real  0m31.399s
    user  0m21.167s
    sys   0m18.927s
    
[/code]


CC BY-SA 4.0
2023-11-20T13:35:17.107
96854
2023-11-20T14:28:22.357
2023-11-20T14:28:22.357
47127
47127
96852
answer


既に回答がついていますが、別解です。  
あまり速くないかもしれませんが、findの実行は１回です。

[code]

    find . -type f | sort | xargs -I {} bash -c 'ls -l --time-style='\''+%Y-%m-%d'\'' {} | awk '\''{print $6, $7}'\''; cat  {} |wc -l'| paste - -
    
[/code]


CC BY-SA 4.0
2023-11-20T14:07:34.933
96855
2023-11-20T14:07:34.933
35558
96852
answer