Search code examples
unixgrepls

How to properly grep filenames only from ls -al


How do I tell grep to only print out lines if the "filename" matches when I'm piping through ls? I want it to ignore everything on each line until after the timestamp. There must be some easy way to do this on a single command.

As you can see, without it, if I searched for the file "rwx", it would return not only the line with rwx.c, but also the first three lines because of permissions. I was going to use AWK but I want it to display the whole last line if I search for "rwx".

Any ideas?

EDIT: Thanks for the hacks below. However, it would be great to have a more bug-free method. For example, if I had a file named "rob rob", I wouldn't be able to use the stated solutions.

drwxrwxr-x 2 rob rob  4096 2012-03-04 18:03 .
drwxrwxr-x 4 rob rob  4096 2012-03-04 12:38 ..
-rwxrwxr-x 1 rob rob 13783 2012-03-04 18:03 a.out
-rw-rw-r-- 1 rob rob  4294 2012-03-04 18:02 function1.c
-rw-rw-r-- 1 rob rob   273 2012-03-04 12:54 function1.c~
-rw-rw-r-- 1 rob rob    16 2012-03-04 18:02 rwx.c
-rw-rw-r-- 1 rob rob    16 2012-03-04 18:02 rob rob

Solution

  • Why don't you use grep and match the file name following the timestamp?

    grep -P "[0-9]{2}:[0-9]{2} $FILENAME(\.[a-zA-Z0-9]+)?$"
    

    The [0-9]{2}:[0-9]{2} is for the time, the $FILENAME is where you'd put rob rob or rwx, and the trailing (\.[a-zA-Z0-9]+)? is to allow for an optional extension.

    Edit: @JonathanLeffler below points out that when files are older than bout 6 months the time column gets replaced by a year - this is what happens on my computer anyhow. You could do ([0-9]{2}:[0-9]{2}|(19|20)[0-9]{2}) to allow time OR year, but you may be best of using awk (?).

    [foo@bar ~/tmp]$ls -al
    total 8
    drwxrwxr-x  2 foo foo 4096 Mar  5 09:30 .
    drwxr-xr-- 83 foo foo 4096 Mar  5 09:30 ..
    -rw-rw-r--  1 foo foo    0 Mar  5 09:30 foo foo
    -rw-rw-r--  1 foo foo    0 Mar  5 09:29 rwx.c
    -rw-rw-r--  1 foo foo    0 Mar  5 09:29 tmp
    
    [foo@bar ~/tmp]$export filename='foo foo'
    
    [foo@bar ~/tmp]$echo $filename
    foo foo
    
    [foo@bar ~/tmp]$ls -al | grep -P "[0-9]{2}:[0-9]{2} $filename(\.[a-zA-Z0-9]+)?$"
    -rw-rw-r--  1 cha66i cha66i    0 Mar  5 09:30 foo foo
    

    (You could additionally extend to matching the whole line if you wanted:

    ^                              # start of line
    [d-]([r-][w-][x-]){3} +        # permissions & space (note: is there a 't' or 's'
                                   # sometimes where the 'd' can be??)
    [0-9]+                         # whatever that number is
    [\w-]+ [\w-]+ +                # user/group (are spaces allowed in these?)
    [0-9]+ +                       # file size (modify for -h switch??)
    (19|20)[0-9]{2}-               # yyyy (modify if you want to allow <1900)
    (1[012]|0[1-9])-               # mm
    (0[1-9]|[12][0-9]|3[012]) +    # dd
    ([01][0-9]|2[0-3]):[0-6][0-9] +# HH:MM (24hr)
    $filename(\.[a-zA-Z0-9]+)?     # filename & optional extension
    $                              # end of line
    

    . You get the point, tailor to your needs.)