14

I tried ls /etc/[ac]* but it shows directories starting with a or c, and their entire contents, not the files starting with "a" or "c".

2
  • directories are one of many types of files. What types of files are you interested in (regular, symlink, device, pipe, socket...)? Commented May 23, 2014 at 13:46
  • It is unclear whether you by "directory" are talking about the contents of the directories, or about the directory names themselves. The command that you show would list the contents of directories that matches the pattern, with ls -d /etc/[ac]* you would not get the contents of matching directories, but would still see the directory names. It is unclear whether this is what you want or if you would want to avoid even listing the directory names.
    – Kusalananda
    Commented Apr 11, 2020 at 11:20

7 Answers 7

27

To avoid listing the contents of directories, you can:

ls -d /etc/[ac]*

That will list the directory names along with ordinary file names starting with a or c.

For completeness, a solution not involving find might be:

ls -ld /etc/[ac]* | grep ^- | tr -s ' ' | cut -d' ' -f9
5
  • My initial reading of the question also made ls -d seem appropriate, but it seems that the original question specifies that no directories should be listed, regardless of expansion or non-expansion.
    – Chris Down
    Commented May 22, 2014 at 3:03
  • 1
    ls -ld /etc/[ac]* | grep ^- | tr -s ' ' | cut -d' ' -f9 don't parse ls. Commented May 22, 2014 at 3:16
  • 1
    @AvinashRaj: Well, the relevance of that advice depends on whether one needs this solution to work once, or forever. If only once, then parsing ls is fair game in my opinion. Commented May 22, 2014 at 3:18
  • 3
    He does have a point. While names in /etc are very likely to be sane, a simple space will break the ls approach since the field numbers will change. +1 for ls -ld though.
    – terdon
    Commented May 22, 2014 at 3:42
  • 1
    You also need to fix the locale (LC_ALL=C), date is not guaranteed to have 3 fields in other locales. Commented May 23, 2014 at 14:01
9

Recursively:

find /etc -type f -name '[ac]*'

If you require non-recursion, you can do this portably:

find /etc/. ! -name . -prune -type f -name '[ac]*'

Or this, non-portably (GNU or a recent BSD find):

find /etc -type f -maxdepth 1 -name '[ac]*'

If you want to do this case insensitively, use -iname instead of -name.

1
  • 1
    Note that -type f is for regular files. If instead you need non-directory files, replace with ! -type d (or ! -xtype d with GNU find if you also want to exclude symlinks to directories). Commented May 23, 2014 at 13:47
3

If you want both directorys (not directory's contents) and files, you can use printf bultin:

printf "%s\n" [ac]*

Example:

$ printf "%s\n" [te]*
examples.desktop
teamviewer_linux.deb
test.php
test.txt
3
  • How will this avoid directories, as requested in the question?
    – Chris Down
    Commented May 22, 2014 at 3:34
  • Oh, my misreading. I think OP want directory but not its contents.
    – cuonglm
    Commented May 22, 2014 at 3:39
  • Sorry about that edit, completely misread.
    – terdon
    Commented May 23, 2014 at 13:32
2

With zsh:

print -rl /etc/[ac]*(.)

Would list the regular files (as in -type f in find) listed in /etc whose name starts with a or c. The (xxx) part at the end of a glob is a zsh-specific feature called globbing qualifier. . as a globbing qualifier means regular file.

If the glob doesn't match, zsh will abort the command. Note that in other Bourne-like shells, if the glob doesn't match, the pattern expands to itself, so ls -d /etc/[ac]* could incorrectly list a file called /etc/[ac]* if there's no file starting with a or c in /etc.

print -rl /etc/[ac]*(^/)

would list the files that are not of type directory and

print -rl /etc/[ac]*(-^/)

would list the files that are not of type directory after resolving symlinks.

1

You may try this command also,

for file in /etc/[ac]*; do echo $file; done | xargs file | awk -v FS=" +" '$2~/directory/ {next;} {print $1}' | sed 's|\/etc\/||g;s/://g'
1

Non-recursive without find:

ls -pd /etc/[ac]* | grep -v '/$'

the -p adds a / at the end for directories, which the grep filters out. Of course doesn't work for filenames which contain special characters like newlines.

1

For display files starting with a:

ls etc |  grep ^a

For displaying files starting with c:

ls etc |  grep ^c
1
  • 1
    this one work for me
    – andyio
    Commented Jul 8, 2021 at 10:35

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