3

ls -d .* lists only hidden "items" (files & directories). (I think) technically it lists every item beginning with ., which includes the current . and above .. directories.

I also know that ls -A lists "almost all" of the items, listing both hidden and un-hidden items, but excluding . and ... However, combining these as ls -dA .* doesn't list "almost all" of my hidden items.

How can I exclude . and .. when listing hidden items?

3 Answers3

3

From the second answer in:

This works on my machine (I'm not using SSH like the OP though):

ls -d .!(|.)

If there are no hidden files or directories you will get an error message:

$ ls -d .!(|.)
ls: cannot access '.!(|.)': No such file or directory

The error message occurs on directories with no hidden files because . and .. are excluded.

shopt consideration

From comments:

ls -d .[!.]* works without extglob

  • Great! This works on my own machine and my work machine. But strangely it doesn't work on the gateway machine - I get the message -bash: syntax error near unexpected token `('. It's not a big deal, but it would be nice for it to work there too – jonnybolton16 May 28 '20 at 11:20
  • @jonnybolton16 I wonder what bash --version returns on each of the three machines? Perhaps that might be a clue. Other than that run diff command on results of shopt output from different machines my give the reason. – WinEunuuchs2Unix May 28 '20 at 11:26
  • 4.2.46(2) for work machine, 4.4.20(1) for local machine and 4.1.2(1) for gateway. From shopt I can see that the gateway has extglob off. This could be the issue. Doing shopt -s extglob made it work; though I could have sworn I did that earlier – jonnybolton16 May 28 '20 at 11:55
  • ls -d .[!.]* works without extglob – jonnybolton16 May 28 '20 at 12:01
  • 1
    I updated the answer from my phone to briefly reflect your new discoveries. – WinEunuuchs2Unix May 28 '20 at 12:32
1

You can use any set of options, and search the output stream for a matching string or not a matching string using grep.

From grep man page:

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.

So for example if my ls -A output is:

   . .. Desktop Documents Downloads

My ls -A |grep "Do" would be:

Documents
Downloads

I can also use invert search using -v to search for anything that is not my expressions.

From grep man page:

-v, --invert-match select non-matching lines

So in your case the expression would be: ls -d .* |grep "[.][a-z]\|[0-9]"

Pizza
  • 1,428
  • No, this doesn't work... it returns empty – jonnybolton16 May 28 '20 at 09:58
  • sorry, I had an extra " at the end of my command - updated the line – Pizza May 28 '20 at 09:59
  • 1
    I didn't include the extra " (I didn't even see it lol). The command ls -d | grep -v "[.]\|[..]" doesn't work – jonnybolton16 May 28 '20 at 10:05
  • 1
    You are correct, you can just use this, without -v: ls -d .* |grep "[.][a-z]" – Pizza May 28 '20 at 10:17
  • Overall the best practice is to find something that is shortest to write and manipulate, but also that works. I tried that in my terminal this time and it works. Will edit my answer in accordance. – Pizza May 28 '20 at 10:18
  • I would ammend to [aA0-zZ9] to capture capitals and numbers – jonnybolton16 May 28 '20 at 10:22
  • Overall the expression is up to you. I just don't have an example of a the file list you have. If you are looking for the most general expression, then yes. You can also add numbers and characters. This method in the answer is very flexible if you would want to continue omitting other files as well. – Pizza May 28 '20 at 10:25
  • Thanks. I'm not sold on this method though. It's returning the results in a single column, rather than spanning the width of the terminal, and it doesn't use colours (my ls is aliased using --color=auto) – jonnybolton16 May 28 '20 at 10:29
0

You can use also find:

find . -maxdepth 1 -type f -name '.*'

which prints out full path, or:

find . -maxdepth 1 -type f -name '.*' -printf "%f\n"

This works also for empty directories / no such files.