6

I need to print a list of "full" relative paths of all the files present in a directory and in its sub-directories. I used to do this with du and grep:

du -a <path_to_directory> | grep -Po '[0-9]+\t\/\K.*'

But du replaces part of the paths with dots if they are too long.

Which is a good alternative?

Parsing ls is not an option.

1 Answer 1

11

The most straightforward option would be find:

$ cd /usr/lib; find .
.
./libxcb-icccm.so.4.0.0
./libbz2.so.1.0.6
./libdca.so.0
./libxcb-composite.so
./libyajl.so
./libswscale.so
./libxvidcore.so.4.3
./libjasper.so.1
./libdrm_intel.so.1
...

It has various tests for filtering such as:

  • -type to filter based on type (regular file f, directory d, etc.)
  • -mindepth and -maxdepth to set the depths to which find should search (not really tests as such)
  • -name and -path to filter based on filename and path, supporting wildcards.
  • and a lot of other tests, for permissions, ownership, times, etc.

It offers a variety of output formats, using the -printf option.


Depending on the shell and the options enabled, you can also use globbing for this purpose. For example, in bash:

$ shopt -s globstar; printf "%s\n" **
accountsservice
accountsservice/accounts-daemon
aisleriot
aisleriot/ar-cards-renderer
aisleriot/guile
aisleriot/guile/2.0
aisleriot/guile/2.0/accordion.go
aisleriot/guile/2.0/agnes.go
aisleriot/guile/2.0/aisleriot
aisleriot/guile/2.0/aisleriot/api.go
...

And in zsh:

$ printf "%s\n" **/*
accountsservice
accountsservice/accounts-daemon
aisleriot
aisleriot/ar-cards-renderer
aisleriot/guile
aisleriot/guile/2.0
aisleriot/guile/2.0/accordion.go
aisleriot/guile/2.0/agnes.go
aisleriot/guile/2.0/aisleriot
aisleriot/guile/2.0/aisleriot/api.go
...
7
  • 1
    find /some/absolute/path -type f -printf '%P\n' comes to mind Mar 24, 2015 at 22:55
  • Nice, I could even finally get rid of directories. find . -type f | sed -r 's/^\///g' and find . -type f | sed -r 's/^\.\///g' did the trick. Thanks
    – kos
    Mar 24, 2015 at 23:09
  • @kos If you want to remove the ./ check out steeldriver's suggestion instead of using sed - it's not recommended for the same reason parsing ls isn't. If you must use sed, use -print0 and sed -z.
    – muru
    Mar 24, 2015 at 23:12
  • @muru Isn't ^\. or ^\.\/ specific enough by the way?
    – kos
    Mar 24, 2015 at 23:28
  • @muru Actually I still have dots in the middle of some path, which I missed at first. So find is not an option. And I'm unable to run shopt inside a bash script, which probably is the expected behavior
    – kos
    Mar 25, 2015 at 1:17

You must log in to answer this question.

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