I have a directory that contains thousands of files, some of which are hidden.
The command ls -a lists all files, including hidden ones, but I need to just list hidden files.
What command should I use?
I have a directory that contains thousands of files, some of which are hidden.
The command ls -a lists all files, including hidden ones, but I need to just list hidden files.
What command should I use?
This command will list only hidden files:
ls -ld .?*
Explanation:
-l use a long listing format
-d, --directory
list directory entries instead of contents, and do not derefer‐
ence symbolic links
.?* will only state hidden files
If you just want the files in your current directory (no recursion), you could do
echo .[^.]*
That will print the names of all files whose name starts with a . and is followed by one or more non-dot characters. Note that this will fail for files whose name starts with consecutive dots, so for example ....foo will not be shown.
You could also use find:
find -mindepth 1 -prune -name '.*'
The -mindepth ensures we don't match . and the -prune means that find won't descend into subdirectories.
Using find and awk,
find . -type f | awk -F"/" '$NF ~ /^\..*$/ {print $NF}'
Explanation:
find . -type f --> List all the files in the current directory along with it's path like,
./foo.html
./bar.html
./.foo1
awk -F"/" '$NF ~ /^\..*$/ {print $NF}'
/ as field separator awk checks for the last field staring with a dot or not. If it starts with a dot, then it prints the last field of that corresponding line.
find is usually a better option for complicated searches than using name globbing.
find . -mindepth 1 -maxdepth 1 -name '.*'
or
find . -mindepth 1 -maxdepth 1 -name '.*' -o -name '*~'
find . searches current directory
-mindepth 1 excludes . and .. from the list
-maxdepth 1 limits the search to the current directory
-name '.*' find file names that start with a dot
-o or
-name '*~' find file names that end with a tilde (usually, these are backup files from text editing programs)
However, this and all of the other answers miss files that are in the current directory's .hidden file. If you are writing a script, then these lines will read the .hidden file and display the file names of those that exist.
if [[ -f .hidden]] # if '.hidden' exists and is a file
then
while read filename # read file name from line
do
if [[ -e "$filename" ]] # if the read file name exists
then
echo "$filename" # print it
fi
done < .hidden # read from .hidden file
fi
Approach 1: ls -d .{[!.],.?}*
Explain: I want to exclude . and .. but include file such as ..i_am_also_a_hidden_file.txt
ls -d .* undesirably shows . and ..ls -d .?* (the current accepted answer) undesirably shows ..ls -d .[!.]* undesirably will not show ..i_am_also_a_hidden_file.txtls -d .{[!.],.?}* is the answerApproach 2: ls -A | grep "\\."
I personally like this way better
I think that you can do it with following command.
ls -a | grep "^\." | grep -v "^\.$" | grep -v "^\..$"
ls -a command you entered, that shows all files and directories in current working directory.
grep "^\." command I appended, that filters output to shows only hidden files(It's name starts with ".").
grep -v "^\.$" | grep -v "^\..$" command I appended, that filters output to exclude ., ..(They are current and parent directory).
If some filenames can have more than a line with "\n", above example could be incorrect.
So I suggest following command to solve it issue.
find -maxdepth 1 -name ".[!.]*"
What else you could have done, is ls .?* Or ls .!(|) that will show you everything in the current dir hidden files/dirs on the top and other files/dirs below
e.g: from my terminal
$ ls .?*
.bash_history .dmrc .macromedia .weather
.bash_logout .gksu.lock .profile .wgetrc
.bash_profile .bashrc.save .ICEauthority .toprc .Xauthority
.bashrc .lastdir .viminfo .xsession-errors
.bashrc~ .dircolors .lynxrc .vimrc .xsession-errors.old
..:
Baron
.adobe:
Flash_Player
.aptitude:
cache config
.cache:
compizconfig-1 rhythmbox
dconf shotwell
Now notice in the above results, it shows you every file/dir with its subdir and any hidden files right below.
[1:0:248][ebaron@37signals:pts/4][~/Desktop]
$ ls .!(|)
.bash_aliases .bashrc1 .bashrc1~
..:
askapache-bash-profile.txt examples.desktop Public top-1m.csv
backups Firefox_wallpaper.png PycharmProjects top-1m.csv.zip
Desktop java_error_in_PYCHARM_17581.log Shotwell Import Log.txt topsites.txt
Documents Music Templates Videos
Downloads Pictures texput.log vmware
Sorry, I cannot comment. to explain the difference here between ls .?* and @cioby23 answer ls -d .[!.]* .??* And why it is actually printing hidden files twice is because literally you're asking twice .??*, .?*, .[!.]* they're the same thing, so adding any of them with different command characters will print twice.
All the answers so far are based on the fact that files (or directories) which names start with a dot are "hidden". I came up with another solution, that might not be as efficient, but this solution does not assume anything about the names of the hidden files, and therefore avoids listing .. in the result (as does the currently accepted answer).
The full command is:
ls -d $(echo -e "$(\ls)\n$(\ls -A)" | sort | uniq -u)
Explanation
What this does is list all the files (and directories) twice,
echo -e "$(\ls)\n$(\ls -A)"
but only showing hidden files once -A.
Then the list is sorted | sort which makes regular (unhidden) files appear twice and next to each other.
Then, remove all lines that appear more than once | uniq -u, only leaving unique lines.
Finally use ls again to list all the files with the user's custom options and without listing the contents of the directories in the list -d.
EDIT (Limitations):
As muru pointed out, this solution will not work correctly if there are files with names such as escaped\ncharacter.txt because echo -e will split the filename into two lines. It will also not work as expected if there are two hidden files with almost the same name except for a special character, such as .foo[tab].txt and .foo[new-line].txt as both of those are printed as .foo?.txt and would be eliminated by uniq -u
With bash, setting the GLOBIGNORE special variable is some non-empty value is enough to make it ignore . and .. when expanding globs. From the Bash docs:
The
GLOBIGNOREshell variable may be used to restrict the set of filenames matching a pattern. IfGLOBIGNOREis set, each matching filename that also matches one of the patterns inGLOBIGNOREis removed from the list of matches. If thenocasegloboption is set, the matching against the patterns inGLOBIGNOREis performed without regard to case. The filenames.and..are always ignored whenGLOBIGNOREis set and not null. However, settingGLOBIGNOREto a non-null value has the effect of enabling the dotglob shell option, so all other filenames beginning with a‘.’ will match.
If we set it to .:.., both . and .. will be ignored. Since setting it to anything non-null will also get this behaviour, we might as well set it to just .
So:
GLOBIGNORE=.
ls -d .*
Alternatively, you can also use echo .*
e.g.
user@linux:~$ echo .*
. .. .bash_aliases .bash_history .bash_logout .bashrc
user@linux:~$
If you prefer it in long list format, just convert the white space to a new line.
user@linux:~$ echo .* | tr ' ' '\n'
.
..
.bash_aliases
.bash_history
.bash_logout
.bashrc
user@linux:~$
you can use the command
ls -Ad .??*
This has the advantage of allowing multi-column listing, unlike the grep-based approach in the ls -a | grep "^\." solutions
To list all hidden files and folders:
ls -ld .*
To list hidden files only:
ls -ld .*|grep -v ^d
To list hidden folders only:
ls -ld .*|grep ^d
You can also use process substitution
diff <(ls -1A) <(ls -1)
Explanation:
Piping the stdout of a command into the stdin of another is a powerful technique. But, what if you need to pipe the stdout of multiple commands? This is where process substitution comes in. Process substitution feeds the output of a process (or processes) into the stdin of another process
So you are piping two outputs into the diff command.
The first command is "ls -1A". The "-A" flag works like the "-a" flag, but it does not show you "." and "..". So it basically shows you all the files and directories (both hidden and not-hidden) in a directory. The "-1" flag displays the output of "ls" one below the other vertically and not in a horizontal list.
I don't like -d because it only shows no matches found if there are no matches.
It also does not show total [size] at top of lines.
I think ls -lA --ignore "[^\.]*" is a better solution.
ls -A | grep "^\."
ls -A lists all files (hidden and non-hidden)grep "^\." filter apart the ones starting with a dotThanks for all the tips on here!
Here's a function for your .bash_aliases file that handles no command arguments, doesn't throw errors on directories without hidden files, appends / on listed directories, and outputs to a single column.
lsa () {
# Exit codes with/without argument are 0 if no hidden files present
EXIT=$(ls -1d .!(|.) |& grep -q "No such file"; echo $?)
EXIT_ARG=$(cd $1; ls -1d .!(|.) |& grep -q "No such file"; echo $?)
# If no argument
if [ $# -eq 0 ]; then
if [ $EXIT -eq 0 ]; then
printf ""
else
ls -1dp .!(|.)
fi
# If argument
else
if [ $EXIT_ARG -eq 0 ]; then
printf ""
else
(cd $1; ls -1dp .!(|.))
fi
fi
}
A long list of answers, let's add one more, which doesn't seem to be included:
$ ls -lA | grep ' \.'
The -A option to ls includes all hidden files, except . and ...
grep, as used above finds . (space, dot) and filters away lines that do not have that.
$ ls -lA | grep -E '^d.* \.
... lists only dirs.
$ ls -lA | grep -Ev '^d.*' | grep ' \.'
... lists only files.
... and that last can be used as alternative for files-only
$ ls -lA | grep -E '^d.*' | grep ' \.'
just remove the -v flag on grep
The code below only shows hidden files:
ls -A | grep "^\."
or
ls -ap | grep -v / | grep "^\."
Follow steps from their official github: https://gist.github.com/barnes7td/3804534
Setup Terminal for Sublime Shorcut subl: Open terminal and type:
~/bin:
mkdir ~/bin
~/bin directory:
ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" ~/bin/subl
Use these instructions unless you know you have zsh
~/.bash_profile file:
echo 'export PATH=$PATH:$HOME/bin' >> ~/.bash_profile
echo "export EDITOR='subl -w'" >> ~/.bash_profile
If you don't know what zsh is you don't have it.
If using zsh add line to ~/.zshrc file:
echo 'export PATH=$PATH:$HOME/bin' >> ~/.zshrc
Set sublime as your default editor
echo "export EDITOR='subl -w'" >> ~/.zshrc
Restart terminal and type:
subl .
Sublime should open up in the current directory.
Check unix commands:
ls
You should get a directory listing.
Put the C:\Program Files\Sublime Text 2 in your PATH.
Create a subl.bat file and save it in the directory: C:\Program Files\Sublime Text 2
Inside the file put:
start sublime_text.exe %*
You can use the command
ls -pa | grep -v /
Explanation of flags:
-p will append "/" indicator to directories-a will list hidden filesgrep -v / commands will return the lines that do not contain a slash.