Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question
4  
Don't parse ls, use find or a loop... –  jasonwryan Oct 10 '12 at 7:26
add comment

2 Answers

up vote 4 down vote accepted

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.

share|improve this answer
    
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 Oct 10 '12 at 8:28
add comment

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.

share|improve this answer
    
To eliminate the total line, skip line 1: … && NR != 1 –  Gilles Oct 10 '12 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 Oct 10 '12 at 23:56
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.