I want to do something to every file in a directory, so I have
for f in /path/* /path/.*; do
[ -e "$f" ] || continue
do_thing "$f"
done
Unfortunately, this also matches .
and ..
, which is undesirable in this case. How can I avoid matching .
and ..
?
To run do_thing
on every file in the current directory, try:
find /path -maxdepth 1 -type f -exec do_thing {} \;
This method avoids looping and avoids parsing ls
.
How it works
find /path
This starts a find
command and tells find to look in directory /path
.
-maxdepth 1
This tells find
to look only in the current directory and not to descend into subdirectories.
-type f
This tells find
that we are only looking for regular files (not directories).
-exec do_thing {} \;
This runs command do_thing
on every file found.
How about using if
to avoid them?
tmp_path=/path
for f in $tmp_path/* $tmp_path/.*; do
if [ "$f" == "$tmp_path/." ] || [ "$f" == "$tmp_path/.." ]
then
continue
fi
[ -e "$f" ] || continue
echo "$f"
done
the following should match all the hidden files and exclude both .
and ..
for f in `ls -a /path | grep -vE "^\.{1,2}$"`; do
# whatever
done
-v
inverts the match, \.
matches the literal dot, {1,2}
matches it once or twice, ^
and $
match the start and end of line, respectively. the -E
flag makes the {m,n}
syntax work. The backticks ` prevent the shell choking on the pipe. (hihi)
clean_path=`ls -a ~/example_dir/ | grep -v -P "^\.{1,2}$"`
for f in $clean_path; do
do_thing $f;
done
ls -a ~/some_dir
command to print out all of the file in the some_dir
directory.
^\.{1,2}$
means, match a string which start (^
) with dot (\.
), the dot may come in 1 to 2 characters ({1,2}
), and that's the end of the string ($
), so it will match both .
and ..
.
Using backtick within a command means "process the result of this command".
grep -v -P
, -v
flag to inverse the answer, so it would exclude the matching file that named .
and ..
. -P
flag to use the Perl regular expression.
Voila, you can now iterate them since the result is only separated by space.