ls command: how can I get a recursive full-path listing, one line per file?

682,783

Solution 1

If you really want to use ls, then format its output using awk:

ls -R /path | awk '
/:$/&&f{s=$0;f=0}
/:$/&&!f{sub(/:$/,"");s=$0;f=1;next}
NF&&f{ print s"/"$0 }'

Solution 2

Use find:

find .
find /home/dreftymac

If you want files only (omit directories, devices, etc):

find . -type f
find /home/dreftymac -type f

Solution 3

ls -ld $(find .)

if you want to sort your output by modification time:

ls -ltd $(find .)

Solution 4

Try the following simpler way:

find "$PWD"

Solution 5

Best command is: tree -fi

-f print the full path prefix for each file
-i don't print indentations

e.g.

$ tree -fi
.
./README.md
./node_modules
./package.json
./src
./src/datasources
./src/datasources/bookmarks.js
./src/example.json
./src/index.js
./src/resolvers.js
./src/schema.js

In order to use the files but not the links, you have to remove > from your output:

tree -fi |grep -v \>

If you want to know the nature of each file, (to read only ASCII files for example) try a while loop:

tree -fi |
grep -v \> |
while read -r first ; do 
    file "${first}"
done |
grep ASCII
Share:
682,783
dreftymac
Author by

dreftymac

Greetings! Ask and answer. Share alike.

Updated on July 15, 2021

Comments

  • dreftymac
    dreftymac almost 3 years

    How can I get ls to spit out a flat list of recursive one-per-line paths?

    For example, I just want a flat listing of files with their full paths:

    /home/dreftymac/.
    /home/dreftymac/foo.txt
    /home/dreftymac/bar.txt
    /home/dreftymac/stackoverflow
    /home/dreftymac/stackoverflow/alpha.txt
    /home/dreftymac/stackoverflow/bravo.txt
    /home/dreftymac/stackoverflow/charlie.txt
    

    ls -a1 almost does what I need, but I do not want path fragments, I want full paths.

  • SourceSeeker
    SourceSeeker over 14 years
    If your system has readlink you can do directory=$(readlink -e $1)
  • John Keyes
    John Keyes over 14 years
    True, but cd/pwd combination will work on every system. readlink on OS X 10.5.8 does not support -e option.
  • jperelli
    jperelli over 12 years
    -bash: /bin/ls: Argument list too long
  • n611x007
    n611x007 over 11 years
    can ls parameters like --sort=extension "redeemed" by this solution?
  • n611x007
    n611x007 over 11 years
    +1 worked for me with 12106 files, and I could use the --sort=extension parameter of ls
  • Admin
    Admin almost 11 years
    you can also use simply : tar cvf /dev/null $PWD
  • om01
    om01 almost 11 years
    @Nakilon what's the closest thing? Does it display output similarly? How would you easily display similar output with a short command?
  • mustafa.0x
    mustafa.0x over 10 years
    find "`pwd`" if the path contains spaces or some other special characters.
  • ccpizza
    ccpizza over 10 years
    @om01: on osx it is a difficult as brew install tree, given you are using homebrew
  • pcantalupo
    pcantalupo almost 10 years
    <3 this command...perfect solution for what I need right now! thank you!
  • Mert Nuhoglu
    Mert Nuhoglu over 9 years
    Can someone please explain the above awk expressions?
  • Salman von Abbas
    Salman von Abbas over 9 years
    How is this any different than find .? -.-
  • Selvin
    Selvin over 9 years
    great answer.. exactly what i needed!
  • Jake Toronto
    Jake Toronto over 9 years
    Interesting, because it shows me stuff I didn't know I wanted to know -- kind of like Google suggest. It turns out, I like knowing how much space each file takes.
  • mariotti
    mariotti over 9 years
    A bit late too. Indeed: how would symbolic links be handled in these cases? As I was thinking about this for an "home made" index of files, somewhat like locate on a single file list. But if I could get the full path, as it is indeed my files, it makes sense (to me) to show me the actual ls output, mainly I guess, dates and full path.
  • mariotti
    mariotti over 9 years
    The target would be: get the 12 or more old HD i have (full HD), make a full path 'ls' output, and use it for some fast 'grep' searching. It makes little sense to back them up, as it is loads of probably already duplicated data. Maybe there is some catalog alike tool but I am not sure if a simple grep for when I need it is better. I mean: a full backup system vs a couple of files...
  • SRG
    SRG over 9 years
    Thanks. I wouldn't have thought by myself of that (nice and short) syntax - i would have used find . -name "*" -exec ls -ld '{}' \; (that one works whatever the number of files is), but your command is way shorter to write ;)
  • xsubira
    xsubira about 9 years
    You can even use printf output in order to display needed contextual info (e.g. find . -type f -printf '%p %u\n')
  • kommradHomer
    kommradHomer about 9 years
    i couldn't list the files exclusivelty. it always lists the directories too. how can i do that?
  • yckart
    yckart almost 9 years
    @SalmanPK If you give find an absolute path like pwd to start with, it will print absolute paths. By the way, "How is this any different than find" ;-)
  • JayB
    JayB almost 8 years
    This solution doesn't omit the directories (each directory gets its own line)
  • kuz8
    kuz8 over 7 years
    ls -ld $(find .) breaks for me if I'm listing a ntfs disk where files have spaces: ls: cannot access ./System: No such file or directory however find with quotes by @SRG works
  • Arnold Roa
    Arnold Roa over 7 years
    any idea how I can remove the filesize wihtout awk ?
  • andrew lorien
    andrew lorien over 7 years
    Also unfortunately you can't sudo ls with a wildcard (because the wildcard is expanded as the normal user).
  • WonderLand
    WonderLand over 7 years
    Use it carefully !!! As said above it also list all directories and the roots directories as well so if you plan to use it to delete a list of files you need to clean this list !
  • ilw
    ilw almost 7 years
    Unknown option '-1'. Aborting.
  • Leo Ufimtsev
    Leo Ufimtsev over 6 years
    Thanks. Btw, would be nice to have this in 1 line for quick copy & paste.
  • Nathan
    Nathan about 6 years
    Can this be formatted with a falg? ie. python pprint.pprint(files)
  • IanS
    IanS about 6 years
    A shorter alternative (depending on your needs) would be find . -ls.
  • jessexknight
    jessexknight almost 6 years
    add this to your .bashrc file: function lsr () { ls -R "$@" | awk ' /:$/&&f{s=$0;f=0} /:$/&&!f{sub(/:$/,"");s=$0;f=1;next} NF&&f{ print s"/"$0 }' } so you can use lsr /path to use this wherever
  • Jayant Bhawal
    Jayant Bhawal almost 6 years
    Tried on Mac OS 10.13.3. find: illegal option -- D
  • Jasper
    Jasper about 5 years
    The other answer should be accepted. This is a good second answer and does indeed answer the question as written, but the best solution is the one using find. The intention of the question is clear (which is not that it has to done using ls), and this answer is better only for those who can't use find. The claim this answer is more "right" because it answers the written question instead of the intended one is pretty ridiculous.
  • TZubiri
    TZubiri about 4 years
    The correct answer is that you can't. This is just a waste of time.
  • Hadrien TOMA
    Hadrien TOMA about 4 years
    OP wants just the full path and nothing else. ls -lR wouldn't meet that goal.
  • Shayan
    Shayan almost 4 years
    But find does not print file sizes :( I want ls -alR but I want each line to contain full path.
  • Max
    Max almost 4 years
    SRG modified to find . -name "*" -exec ls -ld -w1 -Q -x '{}' \; shows file names only and quotes everything for ntfs space characters.
  • Josh
    Josh almost 4 years
    Do you mind explaining the awk code? It looks like you are using a regex to catch lines that end in ":" (the "headers" with parent directory paths), but I get lost after that and definitely don't understand the part where the last field NF is being evaluated as true/false. Thanks!
  • taltman
    taltman over 3 years
    The NF eval is for checking whether the line is blank. It could be replaced with /^$/ for example, but NF is computed anyways. I simplified the awk code as follows, as the provided version is buggy as it omits files at the top-level directory (I edited the answer, but not sure if my edits will be approved): ls -R | awk '/:$/ {sub(/:$/,""); s=$0;next}{ print s "/" $0 }'
  • tripleee
    tripleee about 3 years
    find -ls avoids running an external process for each file and is a lot easier to type.
  • tripleee
    tripleee about 3 years
    @ilw That's weird; I'd think ls -1 is fairly standard; but try just leaving it out if it's unsupported. The purpose of that option is to force ls to print one line per file but that's usually its behavior out of the box anyway. (But then of course, don't use ls in scripts.) (Looking at the POSIX doco, this option was traditionally BSD only, but was introduced in POSIX in 2017.)
  • Denio Mariz
    Denio Mariz almost 3 years
    You don´t need the -exec ls \{\} \; part, since the default behavior of find is to print the full path. That is, find /path -type f does the job if you don´t need the file attributes from ls -l.
  • tripleee
    tripleee almost 3 years
    @kommrad You could adapt the file example and pipe to grep -v directory
  • tripleee
    tripleee almost 3 years
    @Shayan find with the -printf predicate allows you to do everyting ls does, and then some. However, it is not standard. You can use find -exec stat {} \; but unfortunately the options to stat are not standardized, either.
  • tripleee
    tripleee almost 3 years
    ... In the end, unfortunately, the most portable solution might be a Perl or Python script.
  • tripleee
    tripleee almost 3 years
    find without an argument is a syntax error on some platforms. Where it isn't, just find is equivalent to find ..
  • tripleee
    tripleee almost 3 years
    Also unfortunately, ls has a lot of pesky corner cases; see parsing ls
  • linguisticturn
    linguisticturn about 2 years
    All the subfolders will be in the list, not just files.