Avoid matching . and .. when looping through files

2019-07-31 22:41发布

问题:

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 ..?

回答1:

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.



回答2:

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


回答3:

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)



回答4:

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.



标签: sh