views:

259

answers:

7

I'm trying to format the output of ls -la to only contain files modified in December and output them nicely, this is what they currently look like:

ls -la | awk {'print $6,$7,$8,$9,$10'} | grep "Dec" | sort -r | head -5
Dec 4 20:15 folder/
Dec 4 19:51 ./
Dec 4 17:42 Folder\ John/
Dec 4 16:19 Homework\ MAT\ 08/
Dec 4 16:05 Folder\ Smith/

etc..

How can I set up something like a regular expression to not include things like "./" and "../",

Also how can I omit the slash "\" for folders that have spaces in them. Id like to drop the slash at the end. Is this possible through a shell command? Or would I have to use Perl to make modifications to the test? I do want the date and time to remain as is. Any help would be greatly appreciated!

The box has linux and this is being done via SSH.

Edit:

Heres what I have so far (thanks to Mark and gbacon for this)

ls -laF | grep -vE ' ..?/?$' | awk '{ for (i=6; i<=NF; i++) printf("%s ", $i); printf("\n"); } ' | grep "Dec" | sort -r | head -5

Im just having trouble with replacing "\ " with just a space " ". Other than that Thanks for all the help upto this point!

+1  A: 

Here's one of your answers:

How can I set up something like a regular expression to not include things like "./" and "../",

Use ls -lA instead of ls -la.

Instead of printing out a fixed number of columns, you can print out everything from column 6 t the end of the line:

ls -lA | awk '{ for (i=6; i<=NF; i++) printf("%s ", $i); printf("\n"); } '

I don't get the spaces backslashed, so I don't know why you are getting that. To fix it you could add this:

| sed 's/\\//g'
Mark Byers
Im still getting Dec 4 19:51 ./When I run: ls -lA | awk {'print $6,$7,$8,$9,$10'} | grep "Dec" | sort -r | head -5
linux_rookie
ls -A prints all folders beginning with a period apart from `.` and `..`. Are you using standard GNU tools or something else?
Mark Byers
Mark, forgive my ignorance but how do I check and make sure they arent anything other than standard?ls -lA | awk '{ for (i=6; i<=NF; i++) printf("%s ", $i); printf("\n"); } ' > test.txt;head -3 test.txtDec 5 17:18 ./Dec 4 14:50 ../ls --versionls (GNU coreutils) 5.97Copyright (C) 2006 Free Software Foundation, Inc.This is free software. You may redistribute copies of it under the terms ofthe GNU General Public License <http://www.gnu.org/licenses/gpl.html>.There is NO WARRANTY, to the extent permitted by law.Written by Richard Stallman and David MacKenzie.
linux_rookie
That is the standard GNU ls, but your version of coreutils is from 2006. Time for an upgrade perhaps? Having old software increases the risk that you will get hacked.
Mark Byers
I updated my solution to remove the backslashes, and if you do this it will solve your problem, but I strongly suggest that you investigate why your system is returning incorrect results for such a basic operation as ls. There is something seriously wrong with your system if something as simple as ls isn't working as expected.
Mark Byers
Thanks for the solution Mark, I greatly appreciate it, its broken down well so someone at my level can make sense of everything you did.
linux_rookie
+1  A: 

Check and make sure your 'ls' command isn't aliased to something else. Typically, "raw" ls doesn't give you the / for directories, nor should it be escaping the spaces.

Clearly something is escaping the spaces for you for your awk to be printing those files, since awk tends to break field up by whitespace, that's what the \ characters are for.

Spaces is files names are designed specifically to frustrate writing easy script and pipe mashups like you're are trying to do here.

Will Hartung
A: 

well you can drop . and .. by adding grep -v "\." | grep -v "\.\."

not sure about the rest

Simeon Pilgrim
+1  A: 

You could filter the output of ls:

ls -la | grep -vE ' ..?/?$' | awk {'print $6,$7,$8,$9,$10'} | grep "Dec" | sort -r | head -5

If you're content to use Perl:

ls -la | perl -lane 's/\\ / /g;
                     print "@F[5..9]"
                       if $F[8] !~ m!^..?/?$! &&
                          $F[5] eq "Dec"'
Greg Bacon
Thank you this solved my issue with . and ..!
linux_rookie
You're welcome! Glad to help.
Greg Bacon
No objection to doing in perl, if its easier to be done that way and I learn I will be just as content.
linux_rookie
+1  A: 

You can use find to do most of the work for you:

find -mindepth 1 -maxdepth 1 -printf "%Tb %Td %TH:%TM %f\n" | grep "^Dec" | sort -r

The parent directory (..) is not included by default. The -mindepth 1 gets rid of the current directory (.). You can remove the -maxdepth 1 to make it recursive, but you should change the %f to %p to include the path with the filename.

These are the fields in the -printf:

  • %Tb - short month name
  • %Td - day of the month
  • %TM:%TM - hours and minutes
  • %f - filename

In the grep I've added a match for the beginning of the line so it won't match a file named "Decimal" that was modified in November, for example.

Dennis Williamson
Excellent this worked very well, thank you!
linux_rookie
A: 

It really irks me to see pipelines with awk and grep/sed. Awk is a very powerful line-processing tool.

ls -laF | awk '
    / \.\.?\/$/ {next}
    / Dec / {for (i=1; i<=5; i++) $i = ""; print} 
' | sort -r | head -5
glenn jackman
+1  A: 

what's with all the greps and seds???

ls -laF | awk '!/\.\.\/$/ && !/\.\/$/ &&/Dec/ { for (i=6; i<=NF; i++) printf("%s ", $i); printf("\n"); }'
this has an issue of not showing a file whose name ends with a "."
Vijay Sarathi