I would like to find files whose name has only 4 characters.

Example, there are three files under /tmp:

$ ls /tmp

Output should only show file because it only has 4 characters.

  • 1
    If you want to print also hidden files make use of brace expansion: echo /tmp/{.,?}???.
    – jimmij
    Jun 4, 2015 at 12:38
  • What? No grep based solution yet?
    – Cole Tobin
    Jun 4, 2015 at 14:56
  • 1
    @ColeJohnson It's not the best tool for the job. grep matches lines of text, but not all filenames are guaranteed to be single lines of text.
    – jw013
    Jun 4, 2015 at 17:46
  • 2
    Why do you want to do this? Please edit your question and enlighten us. Jun 5, 2015 at 20:06
  • 1
    Also, bytes or characters? beta in UTF-8 is 4 characters and 4 bytes long, while bétá is 4 characters and 6 bytes....
    – Rmano
    Jun 6, 2015 at 17:57

9 Answers 9


Use the ? wildcard for file globbing:

ls -d /tmp/????

This will print all files and directories whose filename is 4-char long.

As suggested by @roaima, the -d flag will prevent ls to display the content of subdirectories that match the pattern.

  • Thanks It works! I have another question how to find the file in sub-directory without /tmp
    – Mike
    Jun 4, 2015 at 11:50
  • 2
    Please open a separate question for this.
    – dr_
    Jun 4, 2015 at 12:16
  • 3
    Note that this won't list hidden file.
    – cuonglm
    Jun 4, 2015 at 18:00
  • 4
    Use ls -d to avoid expansion of any directory matching /tmp/???? Jun 4, 2015 at 21:06
  • 2
    @user913 if simple globbing does the same job, find is overkill. nothing wrong with it otherwise Jun 8, 2015 at 20:46

List files in /tmp only:

cd /tmp
find . ! -name . -prune -path './????' -type f

List files in /tmp recursively:

find /tmp -path '*/????' -type f


find /tmp -type f -print| awk -F/ ' length($NF)  == 4 '

What awk does:

  • Using / as field separator,
  • Finding filename $NF (last field)
  • Computing length
  • And check if value is 4, then print it.
  • 2
    This won't work if filename contains newline.
    – cuonglm
    Jun 4, 2015 at 13:31
  • @cuonglm can file name have new line?
    – Ooker
    Jun 5, 2015 at 10:57
  • 1
    @Ooker: Yes, try touch a$'\n'b
    – cuonglm
    Jun 5, 2015 at 11:17

This seems to me like the most straightforward way to find a file of four bytes:

find /tmp -type f -size 4c

Edit: to find a file name of four bytes:

find /tmp -type f -name '????'
  • 1
    Judging by the example given in the question, OP is looking at file names not contents.
    – jw013
    Jun 4, 2015 at 17:51
  • Ah, of course, not a file of four bytes but a file name of four bytes. That makes sense. Jun 4, 2015 at 17:55
  • This will also match /tmp/somelongpathname/fred, which doesn't match the glob /tmp/???? Jun 4, 2015 at 21:07
  • It is supposed to. /tmp/???? only finds files immediately under /tmp. Jun 4, 2015 at 21:13
  • Can use -maxdepth arg to restrict to immediate entries of /tmp. The original question is unclear on the requirement. Jun 5, 2015 at 15:03

There's also a perl (5.10 or newer) solution:

perl -E 'say for </tmp/????>;'

A slightly more flexible version where you can specify the desired length:

perl -E 'my $w = "?" x shift; say for </tmp/$w>;' 4

"/tmp/" takes 5 characters. That's why there is "9" (5+4) in test

for i in /tmp/* ;
  do [ "${#i}" -eq 9 ] && printf %s\\n "$i";


for i in /tmp/* ;
  do i="${i#/tmp/}"; # to get rid of /tmp/
  [[ "${#i}" -eq 4 ]] && printf %s\\n "$i"; # there is 4 in test!

FWIW. It does not fail on newline (@cuonglm), can be easilly converted to list only 140 character long file names (@don_crissti).


Assuming you're using bash, you can do the following:

shopt -s globstar
shopt -s nullglob

This will put the list of files you want in an array filearray. Newlines (and other exotic characters) in the filename will be handled correctly.

Setting globstar enables ** in glob patterns to match across subdirectories, giving the required recursive search.

Setting nullglob simply causes the expansion to expand to nothing if there are no matches. Otherwise it will expand to itself which is probably not what you want.


As globbing is done by the shell, there is even no need to call ls or find, echo does the trick:

$ echo /tmp/????

Only thing is, if there is no file whose name is 4 characters long, it will just print


You might want a one-liner bash script that checks this and also prints one file per line:

pattern=/tmp/????? ; for f in $pattern ; do if [ $f != "$pattern" ] ; then echo $f ; fi ; done

How about:

ls /tmp | grep -e '^.\{4\}$'    

for a grep based answer.

  • 1
    This won't work if filename contains newline
    – cuonglm
    Jun 4, 2015 at 17:08
  • @cuonglm if your going to be pedantic about newlines, at least apply it evenly across all answers to a question. Any globbing with ?(s) is susceptible to this defect.
    – joe Lovick
    Jun 4, 2015 at 17:30
  • 1
    @joeLovick: You created file with literal \n, not newline
    – cuonglm
    Jun 4, 2015 at 17:55
  • 3
    never parse ls for anything Jun 5, 2015 at 7:43
  • 1
    ls -q | grep -E '^.{4}$' should take care of those file names with funky chars (though they'll appear as question marks in the output). Jun 5, 2015 at 9:46

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