Question

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!

Was it helpful?

Solution

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.

OTHER TIPS

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.

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"'

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'

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

ls -laF | awk '!/\.\.\/$/ && !/\.\/$/ &&/Dec/ { for (i=6; i<=NF; i++) printf("%s ", $i); printf("\n"); }'

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

not sure about the rest

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top