6

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. Like if the current directory is /path/to/somewhere, I want:

somewhere/file 1234
somewhere/other-file 4567

Instead of just

file 1234
other-file 4567

Is that possible?

5
  • 4
    What do you mean by the file directory? A full absolute path? The parent directory? Feb 24, 2012 at 12:07
  • u want pwd in ur output? Feb 24, 2012 at 12:07
  • @MatthewScharley Ofc. the parent directory.
    – Cyclone
    Feb 24, 2012 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, 2012 at 13:10
  • 4
    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, 2012 at 14:16

8 Answers 8

5

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

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

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 (assuming a POSIX shell) is this:

ls -l | DIR=${PWD##*/} awk '{printf("%s/%s %s\n", ENVIRON["DIR"], $9, $5); }'

instead.

In tcsh, as your Illegal variable name error suggests you're using, you'd use:

ls -l | env DIR=$PWD:t:q awk '{printf("%s/%s %s\n", ENVIRON["DIR"], $9, $5); }'

instead.


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 :-)

5
  • It does actually print the full path like: 6452 /usr/local/data/pack_24022012/update.ent
    – Cyclone
    Feb 24, 2012 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, 2012 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, 2012 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, 2012 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, 2012 at 16:26
4

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

find . -mindepth 1 -maxdepth 1 -printf '%p\t%s\n'

(here assuming GNU find for its -printf extension).

Replace . with "$PWD" (or $PWD:q if using tcsh) if you want the full paths of the files. Note that contrary to ls, it includes hidden files and doesn't sort the list of files.

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

and for human readable size:

$ du -bh
1

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

ls -ld "$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 -ld -- "$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"
done
1

I think you only need ls:

ls -sh1 /var/log/mysql/*
0 /var/log/mysql/mysqld.log
4.0K /var/log/mysql/mysqld.log-20140718
4.0K /var/log/mysql/mysqld.log-20140827
4.0K /var/log/mysql/mysqld.log-20140829
  • -s print size of each file
  • -h print human readable sizes
  • -1 print each file in a new line
  • * wildcard globbing which "enables" printing the full path
  • optional: -S sort by size
  • optional: -t sort by time
0

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.

Update:

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 }'
8
  • Getting Illegal variable name. message in bash...
    – Cyclone
    Feb 25, 2012 at 22:30
  • Oh ok, I guess it was that $PWD thing. Please try the above code.
    – Barun
    Feb 26, 2012 at 13:43
  • I do still get Illegal variable name message :/
    – Cyclone
    Feb 26, 2012 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, 2012 at 15:01
  • awk: illegal field $(), name "pwd" input record number 2, file source line number 1 ...
    – Cyclone
    Feb 27, 2012 at 12:06
0

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

Hi the best simple answer is to use du -sh * What this command does it is shows the file sizes in kilobytes, megabytes and GB and TB all with a list of the name of the folder or file in the directory.

1

You must log in to answer this question.

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