First of all, this is not a duplicate of this: Linux ls to show only filename date and size

Because I want to print actual directory name additionally.

I was always using this command:

ls -l | awk '{print $5, $9}'

to get the each file size and name. But now, I need to print the file directory additionally.

Is that possible?

  • 4
    What do you mean by the file directory? A full absolute path? The parent directory? – Matthew Scharley Feb 24 '12 at 12:07
  • u want pwd in ur output? – Balaswamy vaddeman Feb 24 '12 at 12:07
  • @MatthewScharley Ofc. the parent directory. – Cyclone Feb 24 '12 at 12:18
  • If you add -F to ls it will 'classify' names, then directories will print with a trailing /, eg foo/ Unfortunately other files will also have classify chars added as well (executables have * appended to name). – bsd Feb 24 '12 at 13:10
  • 3
    Actually, you should avoid parsing the output of ls. Imagine what would happen if say the username had a whitespace character in it. – rahmu Feb 24 '12 at 14:16

You mean like this, just prepending the current directory to each filename?

ls -l | awk -v PWD=$PWD '{printf("%s %s/%s\n", $5, PWD, $9); }'

(the -v just imports the $PWD shell variable into the awk script).

Or something else?

OK, apparently what you want is

$ cd /some/path/to/somewhere
$ <insert command here>
somewhere/file1 size1
somewhere/file2 size2

Is that correct?

If so, the change you need is this:

ls -l | awk -v PWD=$(basename $PWD) '{printf("%s/%s %s\n", PWD, $9, $5); }'

If you have an older shell, the $() may not work, in which case try:

ls -l | awk -v PWD=`basename $PWD` '{printf("%s/%s %s\n", PWD, $9, $5); }'

instead. I don't have immediate access to any shell that doesn't support $(), but I can't think where else your Illegal variable name error would come from, when this works for me.

If it still doesn't work, please describe your platform, shell, version of awk etc. in your question - the comment thread is getting pretty long and I'm running out of guesses :-)

| improve this answer | |
  • It does actually print the full path like: 6452 /usr/local/data/pack_24022012/update.ent – Cyclone Feb 24 '12 at 20:28
  • Yup, I'm just asking if that's what you want, or if you were asking for something else. – Useless Feb 24 '12 at 22:02
  • Okay, as I said, I want to just print the 'actual' (parent) directory name, where the command is executed at. Fe. I'm executing the ls [..] inside of the /usr/local/data/something then it will list the files this way: something/file1.apx <size> and so on... Hope you got me, in case if not, leave a comment back. – Cyclone Feb 24 '12 at 22:11
  • 1
    You do know that 'actual' isn't a recognised technical term, right? If it's hard to explain clearly, just show sample output in the first place (like you've now done in your comment) – Useless Feb 25 '12 at 15:25
  • Okay, sorry that I didnt explain this clearly. Here is what I get while running your edited command: Illegal variable name. – Cyclone Feb 25 '12 at 16:26

In the spirit of "not parsing ls output", why not use find?:

find . -maxdepth 1 -printf "%p\t%s\n"
| improve this answer | |
  • Seems like this is what OP wants: find $(pwd) -maxdepth 1 -printf "%s\t%p%s\n" – rudimeier Nov 9 '16 at 14:50
  • This is the simplest answer. – not2qubit Nov 14 at 11:44

If you want to include the directory part of the file name in the ls output, include it on the command line.

ls -l "$PWD" | awk '{print $5, $9}'

If you want to print a relative path, arrange to call ls from the right directory so as to print the relative path you want, e.g.

dir=$(dirname "$PWD")
cd .. && ls -l -- "$dir" | …

Do be aware of the pitfalls of parsing the output of ls: if a user name or a group name or a file name contains whitespace, that snippet spews out nonsense.

A reliable, but non-portable, way of listing file attributes in a custom format is stat.

stat -f '%8z %R' -- *
stat -f '%8x %n' -- "$dir"/*

A slower but more flexible way of producing this output is to iterate over the files inside the shell.

for x in *; do
  printf '%8d %s\n' "$(wc -c <"$x")" "whatever/you/want/$x"
| improve this answer | |

This is borrowed from what Useless has suggested above:

/bin/ls -l | awk -v CUR_DIR=$(basename $(pwd)) '{ if ($1 != "total") {printf("%s/%s %s\n", CUR_DIR, $8, $5);} }'

This, however, filters the "total xyz" line. Note that output of ls might differ on different distributions. Mine shows file name in the 8th column (whereas Useless shows it as 9th column). Sample output is shown below:

ds/binary_search.py 1660
ds/growth.png 28262
ds/growth.py 1147
ds/heap.py 1277
ds/postfix.py 969
ds/prim.py 39
ds/queue.py 1188
ds/quicksort.py 2535
ds/QuickSortWeiss.class 2821
ds/QuickSortWeiss.java 3500
ds/sin-cos.py 401
ds/sin-cos-two.png 28509
ds/sorting.py 4997

One last point: it might be helpful to provide the exact location of ls. Otherwise, in the case that ls is aliased to something else, the output might again vary.


The above command doesn't seem to work on all systems, am not sure why. However, this one should work, I hope.

/bin/ls -l | awk  '{ if ($1 != "total") {printf("%s/%s %s\n", $(basename $(pwd)), $8, $5);} }' | awk '{ print $8, $9 }'
| improve this answer | |
  • Getting Illegal variable name. message in bash... – Cyclone Feb 25 '12 at 22:30
  • Oh ok, I guess it was that $PWD thing. Please try the above code. – Barun Feb 26 '12 at 13:43
  • I do still get Illegal variable name message :/ – Cyclone Feb 26 '12 at 14:44
  • Ohh...I'm not sure what's problem with your bash. However, try the above alternative. This should help you. – Barun Feb 26 '12 at 15:01
  • awk: illegal field $(), name "pwd" input record number 2, file source line number 1 ... – Cyclone Feb 27 '12 at 12:06

You could also use tree or stat:

# tree --dirsfirst -a -C -i -h -F --du -L 1 ./

[   0]  Test/
[   0]  vcredist/
[3.0K]  .gitignore*
[1.1K]  LICENSE*
[1.3K]  LICENSE.rtf*
[ 17K]  SomeThing.sln
[8.5K]  README.md

  31K used in 19 directories, 5 files

The --du flag is supposed to get you the size of each directory, but not working on my distro.

# stat --format '%s %N' *

0 './build'
0 './Examples'
1087 './LICENSE'
1343 './LICENSE.rtf'

# stat --printf '%s\t%N\n' *

0       'build'
0       'Examples'
1087    'LICENSE'
1343    'LICENSE.rtf'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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