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?

Cyclone
  • 161
  • 1
  • 1
  • 3

8 Answers8

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

Useless
  • 4,800
  • 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
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.

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
$ du -b

and for human readable size:

$ du -bh
Xaqron
  • 199
  • 9
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
mgutt
  • 467
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 }'
Barun
  • 2,376
  • 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 should provide the version of your bash, Linux, and other related things here. It's difficult for anyone to solve your problem otherwise, I guess. – Barun Feb 27 '12 at 12:55
  • I'm using original bash from FreeBSD 8.2, it doesn't work on Debian 5.0 Lenny eighter, so why don't you test your code first , before posting it?:P – Cyclone Feb 27 '12 at 14:25
  • Seems to work perfectly with mawk 1.2 on Debian 6, and gawk 3.1 on Ubuntu 10.04; bash 4.1 in both cases. I don't have access to other platforms -- hope someone could help you. – Barun Feb 27 '12 at 17:11
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'

not2qubit
  • 1,666
-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.