1

I am trying to use ls to get information about files and directories. My current command fails to properly get the name whenever a file/directory has a space.

I am using this to list all files/directories in a directory:

ls -al --time-style=+%s . | awk '{if ($7 != ".." && $7 != "." && $1 != "total") print $1"\t"$3"\t"$5"\t"$6"\t"$7}'

Say I have 3 directories in my pwd "no-spaces-dir", "some dir", "some other dir", this would be the output:

drwxr-xr-x.     testuser    4096    1349853378      no-space-dir
drwxr-xr-x.     testuser    4096    1349853387      some
drwxr-xr-x.     testuser    4096    1349853359      two

I'm going to say this is an issue with my awk part. So $7 should be the directory name, and obviously I could just add $8 and $9 to get my desired output for the example I set up, but I may not always know a directory will only have 1 or 2 spaces..

How can I keep this other information present (file/directory permissions, user, space, timestamp) and also get the full name in the command's output?

1

2 Answers 2

4

The problem is that awk is parsing the input with white space as field separators. This makes for trouble when you have whitespace as part of a field.

Instead of parsing the output of ls, you can use stat(1) to get what you want along with the "dotglob" bash shell option.

shopt -s dotglob  # Enable * to match files starting with a dot
stat -c $'%A\t%U\t%s\t%Y\t%n' *

The format string outputs the fields you wanted in the format you wanted. The use of $'...' allows the \t to be expanded to a tab. You could insert an actual tab character and drop the leading $ if you wanted.

Read the bash(1) man page for details on dotglob, and pay attention to GLOBIGNORE. Read the stat(1) man page for what you can put in a format string.

1
  • This works wonderfully! I wasn't aware of stat. I like the ability to specify other parameters or a parameter in a different format like that. The GLIBIGNORE info was also useful. Thanks!
    – Rich
    Commented Oct 10, 2012 at 8:28
1

As already mentioned, parsing ls is not the best way to print the content of directory. You problem can be easily solved, however.

As file/directory name is always last column (or columns), instead of printing $7, you can print from $7 to last column. You can do this with:

substr($0, index($0, $7))

So your full command would be:

ls -al --time-style=+%s . | awk '{if ($7 != ".." && $7 != "." && $1 != "total") print $1"\t"$3"\t"$5"\t"$6"\t" substr($0,index($0,$7));}'

Also note that checking if $1 != "total" is not really good idea since it won't work on localized systems (where total may be other word). I suggest using NF>6 to ensure you have enough columns.

2
  • To eliminate the total line, skip line 1: … && NR != 1 Commented Oct 10, 2012 at 22:21
  • Thanks for letting me know how to do it with my old way. I switched to use stat, but it was good for me to see a way to do it with awk. I'm still learning about things like awk, so the substr method and the NF thing was helpful.
    – Rich
    Commented Oct 10, 2012 at 23:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .