Search code examples
linuxbashbusybox

Listing files and folders hierarchy in a limited shell


I'm working on a project of mine which uses a very limited linux busybox shell.

My shell doesn't have commands such as find, awk, grep and I'm trying to get a full list of files on that machine.

So far no luck, but running ls -la /* done half of the work and displayed the files one level deep.
Do you have any idea on how I could run ls recursively to get the full list of files and folders? Maybe you know other methods to do so?

Edit #1:

My ls doesn't have the -R option.

ls -1 -LR /

ls: invalid option -- R
BusyBox v1.01 multi-call binary

Usage: ls [-1AacCdeilnLrSsTtuvwxXk] [filenames...]

List directory contents

Options:
    -1  list files in a single column
    -A  do not list implied . and ..
    -a  do not hide entries starting with .
    -C  list entries by columns
    -c  with -l: show ctime
    -d  list directory entries instead of contents
    -e  list both full date and full time
    -i  list the i-node for each file
    -l  use a long listing format
    -n  list numeric UIDs and GIDs instead of names
    -L  list entries pointed to by symbolic links
    -r  sort the listing in reverse order
    -S  sort the listing by file size
    -s  list the size of each file, in blocks
    -T NUM  assume Tabstop every NUM columns
    -t  with -l: show modification time
    -u  with -l: show access time
    -v  sort the listing by version
    -w NUM  assume the terminal is NUM columns wide
    -x  list entries by lines instead of by columns
    -X  sort the listing by extension

Solution

  • From BusyBox's page I can see you have ls's option -R:

    -R List subdirectories recursively

    So you can just write:

    $ ls -R /
    

    Due to you don't have the -R option, you could try with a recursive shell function like this:

    myls() {
        for item in "$1"/* "$1"/.*; do
            [ -z "${item##*/.}" -o -z "${item##*/..}" -o -z "${item##*/\*}" ] && continue
            if [ -d "$item" ]; then
                echo "$item/"
                myls "$item"
            else
                echo "$item"
            fi    
        done
    }
    

    And then you can call it without arguments to start from /.

    $ myls
    

    If you want to start from /home:

    $ myls /home
    

    If you want to make a script:

    #!/bin/sh
    
    # copy the function here
    
    myls "$1"
    

    Explanation

    • [ -z "${item##*/.}" -o -z "${item##*/..}" -o -z "${item##*/\*}" ] && continue This line just excludes the directories . and .. as well as the not expanded items (if there's no files in a folder, the shell leave the pattern as <some_folder>/*).
      This has a limitation. It doesn't show files which names is just a *..
    • If the file is a directory, it prints the directory name with a / appended at the end to improve the output and then call the function recursively for that directory.
    • If the item is a regular file, it just prints the filename and go for the next one.