

あるDIRに複数の「空白を含むファイル名（PDF名など）」が存在し、日付やWORDを含むファイル名で検索し、のちに結果を表示したいときがあります。

[code]

    ls -la
    -rw-rw-rw-  1 admin administrator  11794593  9月  3  2014 Cambridge University Press Programming in Mathematica An Introduction 2013 .pdf
    
[/code]

このとき、空白がないなら `ls -la` などの後ファイル名のフィールド番号を指定すれば良いのはわかります。

[code]

    ls -la | awk '/pdf/{print $9}'
    Cambridge
    
[/code]

しかし、空白がいくつかありますと、希望通りの結果が得られず難儀しております。  
アドバイスよろしくお願いします。


CC BY-SA 4.0
2020-06-22T00:46:37.167
67883
2020-06-22T04:21:51.950
2020-06-22T03:33:07.713
36528
36528
question
awk grep
awk等で、あるフィールド以降のすべてのフィールドを表示させたい


@cubick さんコメントのように、コマンドの引数で表示させる情報を指定できるなら、それを使えば良いと思われます。

それが出来ない情報やコマンドからも取得したいとか、既に取得済みで全ての情報を含んでテキスト化したファイルから抽出したいといった場合は、`index`や`match`と`substr`が使えるのではないでしょうか？

[awkのmatch()関数の使い方](https://it-ojisan.tokyo/awk-match/)  
[match()関数とsubstr()関数で文字列を切り出す](https://it-ojisan.tokyo/awk-match/#keni_toc_4)

[awkでsubstr()の切り出し開始位置をindex()で指定する方法](https://it-ojisan.tokyo/awk-index-
substr/)

[awkでsubstr()を使って文字列を切り出す方法](https://it-ojisan.tokyo/awk-substr/)

ファイル名,フォルダ名ならこんな感じで:  
(フィールドが9個無い場合、別の物が表示されたので最小桁位置でチェックしています)

[code]

    #!/bin/sh
    ls -la | awk '
    {
      match($0, $9)
      if (RSTART >= 17) {
        datatext = substr($0, RSTART)
        print datatext
      }
    }
    '
    
[/code]

ファイルの日付フィールドから切り出したい場合は数字をずらすだけで:

[code]

    #!/bin/sh
    ls -la | awk '
    {
      match($0, $6)
      if (RSTART >= 11) {
        datatext = substr($0, RSTART)
        print datatext
      }
    }
    '
    
[/code]

`match`ではなく`index`を使う場合はこちら:

[code]

    #!/bin/sh
    ls -la | awk '
    {
      column = index($0, $6)
      if (column >= 11) {
        datatext = substr($0, column)
        print datatext
      }
    }
    '
    
[/code]


CC BY-SA 4.0
2020-06-22T02:25:55.310
67888
2020-06-22T02:42:28.023
2020-06-22T02:42:28.023
26370
26370
67883
answer


cubick さんが指摘されているように「ls -1a」(またはls -1A」)でやるのが良いと思います。

「ls -lA」の出力から空白を再現したファイル名を切り出すのは意外と面倒です。  
以下一応やってみました。  
split()関数でカラムとセパレータを分割して切り出してから、必要部分を出力する感じになります。  
見やすさのために出力の行頭と行末に「|」を入れるようにしています。

[code]

    $ touch "   000" "aaa" "bbb bbb" "ccc ccc   ccc" "ddd ddd    ddd   "
    $ ls -lA
    合計 0
    -rw-rw-r-- 1 hidezzz hidezzz 0  6月 22 11:21 '   000'
    -rw-rw-r-- 1 hidezzz hidezzz 0  6月 22 11:21  aaa
    -rw-rw-r-- 1 hidezzz hidezzz 0  6月 22 11:21 'bbb bbb'
    -rw-rw-r-- 1 hidezzz hidezzz 0  6月 22 11:21 'ccc ccc   ccc'
    -rw-rw-r-- 1 hidezzz hidezzz 0  6月 22 11:21 'ddd ddd    ddd   '
    $ls -lA | awk 'NR>1{split($0,a," ",sep);printf "|" substr(sep[8],2) ;for(i=9;i<=length(a);++i){printf a[i] sep[i]}print "|"}'
    |   000|
    |aaa|
    |bbb bbb|
    |ccc ccc   ccc|
    |ddd ddd    ddd   |
    
[/code]


CC BY-SA 4.0
2020-06-22T02:45:58.373
67891
2020-06-22T02:45:58.373
30745
67883
answer

[code]

    LANG=C ls -laN $1 | awk '{
        re="^([^ ]+ +){7}[^ ]+ "
        match($0, re)
        num = RLENGTH + 1
        print substr($0, num)
    }'
    
[/code]

awkのスクリプトの中で、lsの結果であるファイルを切り出したいとき、ファイル名に空白が含まれるとやっかいですね。  
awkのデフォルトのデリミタは空白ですが、連続するデリミタは1個と解釈されるため、いったんフィールドに分解してしまうと空白の数を復元できません。

lsの結果を使いたいとき、ファイル名までのフィールドを削除するしか解決の方法を思いつきませんでした。  
こちらの環境では、51文字目からファイル名でしたので$0から先頭の50文字を削除しています。  
Nオプションを付けずにlsを実行すると、空白を含むファイルの前後に引用符が付加されますので、Nオプションで抑止しています。

確認に使用したlsのバージョンです。  
ls (GNU coreutils) 8.28

* * *

追記  
状況によって「ファイル名の開始位置が変わる」とのご指摘をいただきましたのでコードを修正しました。  
空白で始まるファイル名にも対応しました。


CC BY-SA 4.0
2020-06-22T02:57:53.753
67894
2020-06-22T04:21:51.950
2020-06-22T04:21:51.950
35558
35558
67883
answer