149

How can I list all the files of one folder but not their folders or subfiles. In other words: How can I list only the files?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Rodrigo
  • 11,909
  • 23
  • 68
  • 101
  • Possible duplicate of [How to get the list of files in a directory in a shell script?](https://stackoverflow.com/q/2437452), [How to list files in directory using bash?](https://stackoverflow.com/q/7265272), [Shell script print out file names when given a folder](https://stackoverflow.com/q/45705896), [List files in current directory with full path using Bash](https://stackoverflow.com/q/22992790), [What expands to all files in current directory recursively?](https://stackoverflow.com/q/1690809), [Show files in current directory using Git Bash?](https://stackoverflow.com/q/28738331), etc. – jww May 30 '18 at 01:09
  • Possible duplicate of [How to get the list of files in a directory in a shell script?](https://stackoverflow.com/questions/2437452/how-to-get-the-list-of-files-in-a-directory-in-a-shell-script) – codeforester May 30 '18 at 01:43
  • 1
    None of the proposed duplicates seem to implement the requirement to omit directories. – tripleee May 30 '18 at 04:12

13 Answers13

209

Using find:

find . -maxdepth 1 -type f

Using the -maxdepth 1 option ensures that you only look in the current directory (or, if you replace the . with some path, that directory). If you want a full recursive listing of all files in that and subdirectories, just remove that option.

carlpett
  • 12,203
  • 5
  • 48
  • 82
  • After my comment to mklement0's answer, I realized that "find ./*.png -maxdepth 1 -type f > pngs.txt" would probably accomplish the same. It does. Without installing a script. – Alex Hall Sep 26 '15 at 05:29
  • 2
    `find` on mac, does not have neither `-type`, nor `-maxdepth` options. – Timofey Jul 03 '16 at 17:36
  • 2
    @Tim: `-type` and `-maxdepth` aren't _options_ in the normal sense; BSD `find` (as used on OS X) calls them _primaries_, and they must come _after_ the filename operand(s) (`.`, in this case; note that, unlike on Linux, the BSD version needs at least one explicit filename operand); the command in this answer definitely works on a Mac. – mklement0 Jul 07 '16 at 16:42
  • 1
    @AlexHall: That's a clever solution (though I suggest `find *.png -maxdepth 0 -type f` to avoid the `./` prefix in the output filenames; also note the `-maxdepth` of `0`, not `1`), as long as all you need is the file _names_ in _alphabetical order_. If you want what `ls` can otherwise do for you (different output format/ordering, inline control over whether hidden items are included or not), supplemented with [multi-]type filtering, the script from my answer can help. – mklement0 Jul 07 '16 at 17:09
  • 2
    To contrast `find * -maxdepth 0 -type f` (an alternative derived from @AlexHall's comment) with `find . -maxdepth 1 -type f` from the answer: `find . ...` invariably includes hidden items, invariably prefixes output filenames with `./`, and, with GNU `find` (Linux), typically outputs an unsorted list. `find * ...`, due to letting the _shell_ perform globbing up front, by default excludes hidden items (can be changed with `shopt -s dotglob`), outputs mere filenames (no prefix), sorted alphabetically. Neither approach includes _symlinks to_ files; use option `-L` to do so. – mklement0 Jul 07 '16 at 17:22
  • @Tim yes, basically because it is not POSIX: http://pubs.opengroup.org/onlinepubs/009695399/utilities/find.html `ls -p | grep -v` is though: https://stackoverflow.com/questions/10574794/how-to-list-only-files-in-bash/46135507#46135507 – Ciro Santilli OurBigBook.com Dec 09 '18 at 18:30
36
ls -p | grep -v /

ls -p lets you show / after the folder name, which acts as a tag for you to remove.

Code42
  • 2,292
  • 1
  • 17
  • 22
  • 1
    It's nice to see an example using `ls` in addition to `find`, since the latter returns relative paths and the former only filenames. Use the right tool for the job. – Ben Amos Mar 21 '18 at 19:05
9
  • carlpett's find-based answer (find . -maxdepth 1 -type f) works in principle, but is not quite the same as using ls: you get a potentially unsorted list of filenames all prefixed with ./, and you lose the ability to apply ls's many options;
    also find invariably finds hidden items too, whereas ls' behavior depends on the presence or absence of the -a or -A options.

    • An improvement, suggested by Alex Hall in a comment on the question is to combine shell globbing with find:

       find * -maxdepth 0 -type f  # find -L * ... includes symlinks to files
      
      • However, while this addresses the prefix problem and gives you alphabetically sorted output, you still have neither (inline) control over inclusion of hidden items nor access to ls's many other sorting / output-format options.
  • Hans Roggeman's ls + grep answer is pragmatic, but locks you into using long (-l) output format.


To address these limitations I wrote the fls (filtering ls) utility,

  • a utility that provides the output flexibility of ls while also providing type-filtering capability,
  • simply by placing type-filtering characters such as f for files, d for directories, and l for symlinks before a list of ls arguments (run fls --help or fls --man to learn more).

Examples:

fls f        # list all files in current dir.
fls d -tA ~  #  list dirs. in home dir., including hidden ones, most recent first
fls f^l /usr/local/bin/c* # List matches that are files, but not (^) symlinks (l)

Installation

Supported platforms

  • When installing from the npm registry: Linux and macOS
  • When installing manually: any Unix-like platform with Bash

From the npm registry

Note: Even if you don't use Node.js, its package manager, npm, works across platforms and is easy to install; try
curl -L https://git.io/n-install | bash

With Node.js installed, install as follows:

[sudo] npm install fls -g

Note:

  • Whether you need sudo depends on how you installed Node.js / io.js and whether you've changed permissions later; if you get an EACCES error, try again with sudo.

  • The -g ensures global installation and is needed to put fls in your system's $PATH.

Manual installation

  • Download this bash script as fls.
  • Make it executable with chmod +x fls.
  • Move it or symlink it to a folder in your $PATH, such as /usr/local/bin (macOS) or /usr/bin (Linux).
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Brilliant. Even if it involves creating another script. I copied and pasted from the plain text source you link to, into a text file, and ran it in Cygwin with this command: fls.sh f *.png > pngs.txt And bingo: a list of .png files without paths. But really, ls doesn't have an option comparable to DOS' "dir /b" switch? I looked through the contents of ls' --help output, and nothing of the sort is there, at least. – Alex Hall Sep 26 '15 at 05:25
  • 1
    @AlexHall: Thanks; tl;dr: try `-1` (the number one); `ls` actually defaults to "bare" output, i.e., filenames only, but when outputting to a terminal uses a column-based layout (multiple filenames per line). To get one filename per output line (which is what `dir /b` does, if memory serves), use the `-1` option, which is actually implicitly on when stdout is _not_ connected to a terminal, such as when sending to a pipe or output file. – mklement0 Sep 26 '15 at 13:23
6

Listing content of some directory, without subdirectories

I like using ls options, for sample:

  • -l use a long listing format
  • -t sort by modification time, newest first
  • -r reverse order while sorting
  • -F, --classify append indicator (one of */=>@|) to entries
  • -h, --human-readable with -l and -s, print sizes like 1K 234M 2G etc...

Sometime --color and all others. (See ls --help)

Listing everything but folders

This will show files, symlinks, devices, pipe, sockets etc.

so

find /some/path -maxdepth 1 ! -type d

could be sorted by date easily:

find /some/path -maxdepth 1 ! -type d -exec ls -hltrF {} +

Listing files only:

or

find /some/path -maxdepth 1 -type f

sorted by size:

find /some/path -maxdepth 1 -type f -exec ls -lSF --color {} +

Prevent listing of hidden entries:

To not show hidden entries, where name begin by a dot, you could add ! -name '.*':

find /some/path -maxdepth 1 ! -type d ! -name '.*' -exec ls -hltrF {} +

Then

You could replace /some/path by . to list for current directory or .. for parent directory.

F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
2

You can also use ls with grep or egrep and put it in your profile as an alias:

ls -l | egrep -v '^d'
ls -l | grep -v '^d'
crogg01
  • 2,446
  • 15
  • 35
  • I wouldn't put this in a script for the reason given above, but another quick-and-dirty solution: ls -F | grep -v '/$' – mooie Jan 25 '19 at 11:33
  • @mooie, what does the '/$' mean or why does it remove the directories from the output of ls? – Classified Apr 07 '23 at 00:24
  • 1
    @Classified "ls -F" displays a slash ("/") immediately after each pathname that is a directory. "grep" uses the dollar sign ("$") to indicate an end of a line. So "grep '/$'" would match all lines outputted by "ls -F" that end in a slash, i.e. directories. "grep -v" prints all non-matching lines, i.e. everything but directories, which will be file names (and symbolic links). – mooie Apr 08 '23 at 10:30
2

find files: ls -l /home | grep "^-" | tr -s ' ' | cut -d ' ' -f 9

find directories: ls -l /home | grep "^d" | tr -s ' ' | cut -d ' ' -f 9

find links: ls -l /home | grep "^l" | tr -s ' ' | cut -d ' ' -f 9

tr -s ' ' turns the output into a space-delimited file the cut command says the delimiter is a space, and return the 9th field (always the filename/directory name/linkname).

I use this all the time!

Richard
  • 47
  • 2
1

You are welcome!

ls -l | grep '^-'

Looking just for the name, pipe to cut or awk.

ls -l | grep '^-' | awk '{print $9}'

ls -l | grep '^-' | cut -d " " -f 13
Anthony Rutledge
  • 6,980
  • 2
  • 39
  • 44
0
{ find . -maxdepth 1 -type f | xargs ls -1t | less; }

added xargs to make it works, and used -1 instead of -l to show only filenames without additional ls info

arghtype
  • 4,376
  • 11
  • 45
  • 60
Anabioz
  • 11
  • This has some merit, in that it enforces sorting by time, though there are arguably less clumsy ways to do that with `find -printf0 '...' | sort -z` – tripleee May 30 '18 at 04:11
0

You can one of these:

echo *.* | cut -d ' ' -f 1- --output-delimiter=$'\n'
echo *.* | tr ' ' '\n'
echo *.* | sed 's/\s\+/\n/g'
ls -Ap | sort | grep -v /   
Abdullah
  • 93
  • 14
0

This method does not use external commands.

bash$ res=$( IFS=$'\n'; AA=(`compgen -d`); IFS='|'; eval compgen -f -X '@("${AA[*]}")' )

bash$ echo "$res"
. . .
mug896
  • 1,777
  • 1
  • 19
  • 17
0

to list only file names (and directories at final point) without folders and anything else (properties, sizes etc) I used:

  ls -aRp 
  • a=all entries (not ignore entries start with ".")
  • R=recursive (in all subfolders)
  • p=append "/" indicator to directories (if you like to clean them later) eg. /temp/list/a1/ will be listed as /a1 only

if you like to compare file existence in two different places then apply this too but it sort all files and directories independently of folder structure.

  ls -aRp |  sort --dictionary-order  
Estatistics
  • 874
  • 9
  • 24
-2

Just adding on to carlpett's answer. For a much useful view of the files, you could pipe the output to ls.

find . -maxdepth 1 -type f|ls -lt|less

Shows the most recently modified files in a list format, quite useful when you have downloaded a lot of files, and want to see a non-cluttered version of the recent ones.

Abhay
  • 1
  • 3
  • 3
    This probably doesn't behave as you expect! `ls` doesn't read standard input, so it's useless to pipe anything to `ls`. Did you miss `xargs`? – gniourf_gniourf Mar 04 '15 at 07:12
  • To put it differently: the `find` command in this answer is completely _ignored_; the overall command is the same as `ls -lt | less`, which performs _no_ type filtering. – mklement0 Jul 07 '16 at 17:34
  • 1
    Though with GNU `find` you could do `find . -maxdepth 1 -type f -ls`. It also seems to work on Mac OS, though I believe `-maxdepth` and `-ls` are not properly portable options. – tripleee May 30 '18 at 04:08
-2

"find '-maxdepth' " does not work with my old version of bash, therefore I use:

for f in $(ls) ; do if [ -f $f ] ; then echo $f ; fi ; done

  • The use of `for f in $(ls)` is doubly wrong. You could fix that with `for f in *`but then it would break because you are not quoting the argument to `echo` properly. – tripleee May 30 '18 at 04:06